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

I have a list if products organized with a ParentID and ID and I need to be able to select and display them as organized Ordered by Name.

This article shows a good example using the World-Continent-Country-City-etc. example: http://microsoft.apress.com/asptodayarchive/72582/backing-up-files-from-asp

World
World-Asia
World-Europe
World-Europe-France
World-Europe-France-Paris
World-North America
World-North America-New York
World-North America-New York-New York City

but it does not work with mySQL

table: Items
fields: ID, Name, Description, ParentID, Cost
ID is primary and auto_increment, INT
ParentID is also INT

I was thinking of exporting them to a Hash list or even an Array, then resorting, but was hoping for one good mySQL statement to help. That was when I found out I could use this statement:

SELECT * FROM Items WHERE ParentID IN ( SELECT ID FROM Items ) AND Sto +reID = 2 ORDER BY ParentID, Name
and I would need to run it for at least 4 levels deep.

Here's what I used to use when things were originally pre-sorted. New items were added and they now appear isolated at the bottom of the list.

my $select="SELECT * FROM Items WHERE StoreID = $storeID"; &ExecureDB($select); while ( my ($ID, $NM, $DES, $PI, $PRC)=$sth->fetchrow_array ) { my ($rate, $PAD); # Setup for   Padding unless ($PI == 0) { $rate=4; if ($lp == $PI) { $c1 = $ID; } # Last Parent ($lp) & 1st Child ($c +1) elsif ($c1 == $PI) { $c2 = $ID; $rate*=2; } # Save 2nd Child ($c +2) elsif ($c2 == $PI) { $c3 = $ID; $rate*=3; } # Save 3rd Child ($c +3) elsif ($c3 == $PI) { $c4 = $ID; $rate*=4; } # Save 4th Child ($c +4) else {$rate*=5;} $PAD="  " x $rate; } else { ($c1, $c2, $c3) = ('', '', ''); $lp=$ID; } # Clear Memory print "$PAD $NM - $PRC - $DES", br;

I use this for populating an <OPTION> field with values and all. It's just modified for easy testing now.

Thanks in advance for your guidance.

Replies are listed 'Best First'.
Re: Parent/Child Association with mySQL statements
by moritz (Cardinal) on Sep 07, 2008 at 22:56 UTC
    The article Managing Hierarchical Data in MySQL might be of interested for you.

    The way you store your tree now (by storing the parent ID) means that you have to recurse to retrieve the nesting depth, and that you need to execute one sql statement per level. Other ways of storing the tree (as described in the article above) might work better, but it really depends on what you do with your data, and how often you do it.

Re: Parent/Child Association with mySQL statements
by perrin (Chancellor) on Sep 08, 2008 at 01:14 UTC
    You could convert that Microsoft approach to MySQL. It has stored procedures. I don't really see the point though. The simplest way to work with tree data in a database is to just walk the tree with recursive calls to the database (SELECT id FROM table WHERE parent_id = ?). There are probably even some CPAN modules to help with this. Don't make it any harder than that unless you're having some kind of performance problems.
Re: Parent/Child Association with mySQL statements
by Corion (Patriarch) on Sep 08, 2008 at 06:44 UTC

    Another thing to look at if you want to eliminate the recursive retrieval of rows are Nested Sets by Joe Celko. It makes insertion a bit slower but retrieval is much faster than repeated queries for every level of the tree.