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

This is the third SOPW on this topic in the past few days, please bare with me. I've asked here and on a MySQL forum and have tried piecing things together to get something to click in my mind how it all works.

In short, I'm looking for a way to create an ininite-depth category system with as many sub categories as the admin wants. I've now begun using the parentid field to link back to the upper next category but now I'm confused on how to pull back the entire path/tree.

This is a print out of my table

id parentid name Edit Delete 1 0 Animals Edit Delete 2 1 Mammals Edit Delete 3 1 Fish Edit Delete 4 2 Dog Edit Delete 5 2 Cat Edit Delete 6 3 Fresh Water Edit Delete 7 3 Salt Water Edit Delete 8 8 Sharks Edit Delete 9 8 Small Critters Edit Delete 10 9 Shrimp Edit Delete 11 9 Crab Edit Delete 12 9 Lobster
My structure is something like..
Animals / \ Mammals Fish / \ / \ Dog Cat Fresh Water Salt Water / / \ \ Sharks Dolphins Critters / | \ Shrimp Crab Lob +ster (sorry about my crappy ascii art
How would I go about printing this out in such a way I can see all the paths of each category in an assorted way?

I need it to be alphabetized by the root-most categories first, then the next, and next but all have to be a-z order.

Specifically I'm trying to add this to an HTML form field where each of them would display as <options> with each sub category bulleted/indented a little more than the last.

I saw some example code on dev mysql to go through it using OUTTER and INNER JOINS but they're assuming you know exactly how many categories you have in your table. Assume you have no idea because there could be an ininite depth in real life.

I appreciate all your help on this. I think I'm getting a little closer to what I need

Replies are listed 'Best First'.
Re: Database categories
by bobf (Monsignor) on Apr 03, 2007 at 00:26 UTC

    First, I would suggest that you separate your functions so you're not trying to mix db queries with HTML presentation. I'd probably fetch the data from the db, munge the structure as needed, and then pass it to a templating system (such as HTML::Template) for display.

    Recently I read a couple of articles about how to store tree structures in relational databases. Based on my browser history, they included Managing Hierarchical Data in MySQL and Storing Hierarchical Data in a Database. The latter explains both the adjacency list model (a recursion method) and the modified preorder tree traversal method. Examples of code to retrieve the tree are given for both types (but they're in php).

    Finally, Wikipedia has an entry for hierarchical data model. While the content may be nothing new to you, there are several links to other resources that might be helpful.

Re: Database categories
by parv (Parson) on Apr 02, 2007 at 23:39 UTC
    I was reading recently about keeping a hierarchy in a RelationalDBMS, and all the articles were pointing to "Nested Set" usage instead of "Adjacency List" that you have currently. Managing Hierarchical Data in MySQL by Mike Hillyer is one such article.
Re: Database categories
by eric256 (Parson) on Apr 02, 2007 at 23:49 UTC

    You could use a recursive function to drive down into your tree structure. You hand it the root node, and it then runs itself on each of the children using them as the root nodes. The function would return a hash of nodes with the keys being the node, and the value being a hashref of the children. Then you just iterate over the final list using the keys, and if there are values follow those as well. In fact i think you could build an iterative solution that just does that last bit.


    ___________
    Eric Hodges
Re: Database categories
by Anno (Deacon) on Apr 03, 2007 at 10:31 UTC
    According to your table, "Sharks" has the sub-categories "Small Critters" and "Sharks"(!). That doesn't make sense. Both should probably be subcategories of "Salt Water".

    The typical representation in Perl of a tree like yours would be a hash of arrays. Keys are the category names and values hold the list of corresponding sub-categories. Leaving all database issues aside, I'll assume (a corrected version of) your table is presented as a text file. The following code builds the tree hash %tree from the data. The sub print_tree then prints an indented table of the categories.

    my @names; my %tree; while ( <DATA> ) { chomp; my ( $id, $parent, $name) = (split ' ', $_, 5)[ 2, 3, 4]; $names[ $id] = $name; if ( $parent ) { push @{ $tree{ $names[ $parent]} }, $name; } } print_tree( 'Animals', \ %tree, 0); exit; use constant INDENT => ' '; sub print_tree { my ( $root, $tree, $level) = @_; print INDENT x $level, $root, "\n"; for ( @{ $tree->{ $root} } ) { print_tree( $_, $tree, $level + 1); } } __DATA__ Edit Delete 1 0 Animals Edit Delete 2 1 Mammals Edit Delete 3 1 Fish Edit Delete 4 2 Dog Edit Delete 5 2 Cat Edit Delete 6 3 Fresh Water Edit Delete 7 3 Salt Water Edit Delete 8 7 Sharks Edit Delete 9 7 Small Critters
    Anno
      Thanks for the information but I can't figure out how to query the MySQL data in such a way I could process the information with your subroutines.
[OT]Re: Database categories
by lidden (Curate) on Apr 03, 2007 at 12:12 UTC
    I know your structure was just an example but dolphins are mammals not fish.
      Howdy!

      Actually, there are dolphins that are fish as well as dolphins that are mammals.

      yours,
      Michael