faqts : Computers : Programming : Languages : PHP : Common Problems : Tips and Tricks

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

31 of 35 people (89%) answered Yes
Recently 9 of 10 people (90%) answered Yes

Entry

How can I store a hierarchical structure in a database?
How are folder systems stored in a relational database?

Aug 25th, 2000 05:14
Kai Amrhein, Mårten Svantesson, Loren Siebert, Nathan Wallace, Nathan Wallace


This is one of the more interesting problems to solve using a relational
database...<g>

If you can get a hold of "SQL for Smarties" by Joe Celko it has a great
chapter on solving this problem.  The problem with the common solution
of just keeping a pointer to the parent is that you can end up needing
recursive queries.

The solution is once of those very simple but I would never have thought
of it approaches.  Basically you have to think of the folders as sets. 
So, Linux would be a big set that contained smaller sets like Red Hat
and Mandrake.  Each of those sets can also contain smaller sets and so
on down your hierarchy.

You then lay these sets out flat and give each one a left and right
index.

     3--RPM--4 5--GIMP-6

   2------RedHat---------7  8-----------Mandrake----------9

 1---------------------Linux--------------------------------10

Notice how the indexes for linux completely contain all the other
indices.

You can do really cool queries with this structure like show me all
parents for the folder called $id:

    select *
    from   folders as parents, folders as children
    where  parents.leftindex < children.leftindex
    and    parents.rightindex > children.rightindex
    and    children.id = $id

or show me all the leaves of the tree:

    select *
    from   folders
    where  leftindex = rightindex - 1;

and so on...

The inserts get pretty hairy though as you have to update all the
indices...

BTW, databases like Oracle have a heap of SQL extensions to let you do
hierarchical stuff much more easily...

Don't you wish you were using an object database...<g>

**********
I use Oracle 8, and it provides support for hierarchies using the 
CONNECT BY and PRIOR clauses. It's not ANSI SQL, but it's a lot easier 
than the scheme outlined above. -loren
**********

For some applications a suitable solution is to use the PHP function
serialize to make a string of an array holding hierarchial data.
This string could then be stored in a text field.

WARNING: If you in PHP3 unset an element in an array and the serialize 
it the element will still be there when you retrieve the data with 
unserialize. It's value will be the empty string.

Hi there,

I'va seen and used a different approach. Basically, it's using the
following table-layout:

filed1: 	id	int not null 
field2:		number	int not null
field3:		level	int not null
...(and more fields containing your specific information)
And thats it.
Now what is most important is to get the right understanding for the
usage of the number field. Think of your tree completely expanded,
displaying all nodes.
The topmost entry has number one, as well as level one. The second entry
has number two, and either level two (if it's a child-node of entry one)
or level 1 if it's not. And so on. The third entry has number three ...

In order to find an entry's parent, just select all entrys with a
smaller number than your childentry, then start with the last of the
resulting entrys (it's number is number of childentry minus 1) and check
if it has a level of (childentry's-level minus 1). If it does, it's the
parent. If it doesn't, check the next resultiing entry (number =
childentry-number minus 2) and so on...

To find all children of an entry, just reverse the described process.

Upon inserting or deleting entries, you just have to increase/decrease
the number of all following entries (update docs set
number=number-$entryCount);

Hope this helps,
Kai Amrhein