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

Background
I am trying to do something similar with a more complicated problem so here is an example similar to what i am trying to achieve.
I am pulling some data from a table and trying to lay it out in an particular order. To be spacific as you can see in my example sql(prepare) statement, i am pulling in info about a school and ordering it by minor.
here is a sample of the code

$SQL_report = "select distinct student_id, student_name, student_address, student_gpa, college from SCHOOL where MINOR = 'CS' ORDER BY student_id"; $sth->execute; while (@row = $sth_report->fetchrow_array) { $student_id = (defined $row[0]) ? $row[0] : ''; $student_name = (defined $row[1]) ? $row[1] : ''; $student_address = (defined $row[2]) ? $row[2] : ''; $student_gpa = (defined $row[3]) ? $row[3] : ''; $college = (defined $row[4]) ? $row[4] : ''; ## Make our html look better if no data. $student_id = " " if ($student_id eq ""); $student_name = " " if ($student_name eq ""); $student_major = " " if ($student_address eq ""); $student_gpa = " " if ($student_gpa eq ""); $college = " " if ($college eq ""); } # End of while

Problem
Everything is working just fine on the DBI side and i can get data which at present looks something like this.

id, name, addrss, major, gpa, college id, name, addrss, major, gpa, college id, name, addrss, major, gpa, college id, name, addrss, major, gpa, college
and is ordered too by id_number. which is exactly what it should be like, BUT
I need to somehow sort this incomming data by college. Example:
BUSINESS SCHOOL id, name, address, gpa id, name, address, gpa id, name, address, gpa ENGINEERING id, name, address, gpa id, name, address, gpa id, name, address, gpa NURSING id, name, address, gpa id, name, address, gpa id, name, address, gpa
I have tried to use a few different ways using loops but i cant seem to get it to come out right. As always any input will go a long ways....
Thanks

Edit by dws for tag cleanup

Replies are listed 'Best First'.
Re: Sorting data pullled in by DBI
by dws (Chancellor) on Mar 17, 2002 at 23:59 UTC
    (the data) is ordered too by id_number. which is exactly what it should be like, BUT I need to somehow sort this incomming data by college.

    Let the database do the work.

    $sql = <<SQL; SELECT DISTINCT student_id, student_name, student_address, student_gpa, college FROM school WHERE minor = 'CS' ORDER BY college, student_id SQL
    All you need do then is recognize when "college" changes.

Re: Sorting data pullled in by DBI
by seattlejohn (Deacon) on Mar 17, 2002 at 23:54 UTC
    You can specify multiple ORDER BY fields in your SQL statement. Something along these lines would get you the data in the right order:
    ...ORDER BY college, student_id

    Once you've got that, you could set up your output loop so that it compares the current value of college to the one in the previous record; if it's different, you print a header with the new information. Something like this (untested):

    my $college_last =''; while (@row = $sth_report->fetchrow_array) { # assign $student_name etc. print "<h1>$college</h1>" if $college ne $college_last; $college_last = $college; # print the actual record contents }
(jeffa) Re: Sorting data pullled in by DBI
by jeffa (Bishop) on Mar 18, 2002 at 00:32 UTC
    Everybody has told you how to sort (college, then id), but nobody told you to USE STRICT!!! ;)

    Now, some handy short-cuts in Perl programming:

    Instead of using the ternery operator twice on each column for each row, you could just handle empty columns in the first check:

    $student_name = (defined $row[1]) ? $row[1] : '&nbsp;'; $student_blah = .... ad naseum
    Or you could avoid all that extra typing by utilizing map:
    while (my @row = $sth_report->fetchrow_array) { @row = map { $_ || '&nbsp;' } @row; # .... rest of code }
    Also,the only variable you need is one to store the college (actually, you don't even need that one either! :D) ... the rest can be kept in @row, which can be then stored in a hash whose keys are the colleges, and whose values are the rows of the students (ordered by id) who belong to that college:
    my %college; while (my @row = $sth_report->fetchrow_array) { @row = map { $_ || '&nbsp;' } @row; my $college = pop @row; push $college{$college}, [@row]; }
    And some code to print it back out:
    foreach my $college (keys %college) { print "$college:\n"; foreach my $row (@{$college{$college}}) { print "\t", join(', ', @$row),"\n"; } }
    Hope this helps. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      My favorite idiom for defaulting a set of values is:
      # psuedocode $_ = DEFAULT for grep !CONDITION, @VALUES; # as it applies in this situation $_ = '&nbsp;' for grep !$_, @row;

      -Blake

        The problem with !$_ (and jeffa's map example), is that it tests for truth, so you also end up substituting any values that match 0 instead of only those that are undef.

        Perhaps you meant to use !defined instead?

            --k.


Re: Sorting data pullled in by DBI
by cyocum (Curate) on Mar 17, 2002 at 23:55 UTC

    You could modify your SQL to use "GROUP BY college" and "ORDER BY student_id". Also, you could use Perl's sort function. This will negate the need for your loops and be much cleaner code.

Re: Sorting data pullled in by DBI
by Ryszard (Priest) on Mar 18, 2002 at 00:05 UTC
    order by college, id should do the trick.

    One method i've used to do something similar is using the 1st column as a hash key, and the rest of the columns pushed on to an array.

    #fetch the rows into an array reference my %rethash; while (my @row = $sth->fetchrow_array){ # for a multicolumn query, the 1st column becomes the hash key push @{$rethash{shift(@row)}}, @row; }

    I dont see why it couldnt be rearranged to do achieve what you need in order to provide a more direct data structure, ie use the college as the hash key then structure the rest of your data underneath it (as a hash or array).

Re: Sorting data pullled in by DBI
by data67 (Monk) on Mar 17, 2002 at 23:49 UTC
    one mistake i made in the inital post was that i said i ordered my trial test by minor, this is wrong i ordered it by student id as you can see from my SQL. Which is the way i'll sort my report.