bigup401 has asked for the wisdom of the Perl Monks concerning the following question:

guys i know my join not good but its like sample wat i want to do

$user_id = '1'; TABLE USERS usrid firstname lastname country city ------------------------ 1 john doe uk landon 2 jane deo uk landon TABLE MSG msg_id msg_from msg_to ---------------------- 1 ID 1 ID 2 EXAMPLE msg_id msg_from msg_to ---------------------- 1 ID 1 - get sender firstname and lastname and his userid from ta +ble users ID 2 my $data = $DBH->prepare("SELECT msg_id, firstname.usrid, lastname.usrid AS msg_from FROM msg JOIN users firstname.usrid ON msg_from = firstname.$user_id AND last +name.usrid ON msg_from = lastname.$user_id"); $data->execute(); $data_check = $data->fetchall_arrayref(); foreach $data_check ( @$datainfo) { ($var1 #userid, $var2 #firstname, $var3 #lastname) = @$datainf +o; }
I WANT TO OUTPUT SOMETHING LIKE userid firstname lastname 1 John Deo

Replies are listed 'Best First'.
Re: output results from sql join
by roboticus (Chancellor) on Sep 28, 2018 at 13:22 UTC

    bigup401:

    It looks like you're trying to get the sender and recipient user names for messages and are having trouble with the SQL. You can use the same table multiple times with a different alias each time as shown below. I'm aliasing the USERS table to SND for the sender and to REC for the recipient to get the first and last name of both the sender and recipient for each message:

    SELECT M.msg_id, SND.firstname as snd_fname, SND.lastname as snd_lname, REC.firstname as rec_fname, REC.lastname as rec_lname from MSG as M -- We'll use SND as the alias for the sender join USERS as SND on M.msg_from = SND.usrid -- and REC as the alias for the recipient join USERS as REC on M.msg_to = REC.usrid

    If you're going to fetch all the information as arrays, you don't actually need to alias the column names, and you could just print it as you were suggesting. But you need to be careful with your variable names. You're trying to use $data_check in two places, and you haven't loaded $datainfo. I've changed it a little:

    $data->execute(); my $data_check = $data->fetchall_arrayref(); for my $row (@$data_check) { my ($msgid, $snd_fname, $snd_lname, $rec_fname, $rec_lname) = @$row +; printf "% 6u %-32.32s %-32.32s\n", $msgid, join(" ", $snd_lname, $snd_fname), join(" ", $rec_lname, $rec_fname); }

    However, fetching all the data at once might be a problem when you're dealing with large datasets. Also, by fetching the data as arrays, then any change to your select statement will require you to change the code that converts each array slot into an individual variable. For that reason, I normally fetch a row at a time and fetch hashrefs instead of arrays, like this:

    $data->execute(); my $data_check = $data->fetchall_arrayref(); while (my $row = $data->fetchrow_hashref) { printf "% 6u %-32.32s %-32.32s\n", $row->{msgid}, join(" ", $row->{snd_lname}, $row->{snd_fname}), join(" ", $row->{rec_lname}, $row->{rec_fname}); }

    Here, since I've fetched the data as hashes, I can just use the column aliases as the keys for each row. That way, I don't have to map the columns to variables, instead I can just use the aliased column names, and the order doesn't matter at all.

    I hope this helps. I couldn't quite tell exactly what you were asking, so I just tossed out my thoughts. I haven't tested any of the code, so if there are any syntax errors, let me know and I'll update it with corrections.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      thanks alot roboticus. and i made some changes according to wat i want

      the problem i have where to put placeholder in mysql statment to be safe from sql injection. second my statement is like this

      $myid = 1; select msg_from FROM msg WHERE msg_to = $myid so am selecting only where msg came from who sent it where all people +sent msg to me - my userid 1 msg_from is the id which shows this msg is from this userid from tble +users. so msg_to is my userid the acct owner. so msg comes to me. but i need +to see who sent them.
      so this is msg_from = userid msg_to = to me. my userid (1) so am selecting all people who sent msg to my userid -my userid 1 bt the problem is in the sql statement bt the rest is ok

      thanks alot

        bugup401:

        Yeah, using placeholders is perfect for avoiding SQL injection attacks. To do so, you just put a question mark in place of the values you need to substitute. Then when you execute the statement, you provide one value for each question mark in your statement:

        my $STMT = $DBH->prepare(q{ SELECT SND.firstname as snd_fname, SND.lastname as snd_lname, REC.firstname as rec_fname, REC.lastname as rec_lname from MSG as M -- We'll use SND as the alias for the sender join USERS as SND on M.msg_from = SND.usrid -- and REC as the alias for the recipient join USERS as REC on M.msg_to = REC.usrid where M.msg_id = ? }); # Fetch the data for message 5 my $msg_id = 5; $STMT->execute($msg_id); while (my $row = $STMT->fetchrow_hashref) { # do stuff with the data }

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: output results from sql join
by cavac (Prior) on Oct 02, 2018 at 07:08 UTC

    Other already figured out the problem. BUT there is another big one in your script: Your are not checking the return codes from the database calls. You should always check prepare() and execute() worked without error - not doing it will result in you banging your head against the wall sooner or later.

    Just saying...

    "For me, programming in Perl is like my cooking. The result may not always taste nice, but it's quick, painless and it get's food on the table."
      BUT there is another big one in your script: Your are not checking the return codes from the database calls.

      And that's usally not needed IF you use RaiseError:

      my $dbh=DBI->connect( $dsn, $user, $pass, { RaiseError => 1, PrintError => 0, AutoCommit => 1, } );

      Any failing DBI method will automatically raise an error (i.e. die), no extra code required. See also DBI.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)