Та форум байгуулах, өөрийн вебсайтаас майлын жагсаалтийн мессежийг хэвлэх аль эсвэл өөрийн CMS -г бичих тохиолдолд, таньд өгөгдөлийн санд шаталсан хэлбэрийн өгөгдлийг хадгалах хэрэг болдог. Мөн XML шиг өгөгдлийн сан хэрэглээгүй, хүснэгтүүд нь шаталсан биш энэ нь зүгээр дан жагсаалт хэлбэртэй бол, Та дан жагсаалт хэлбэрээс шаталсан хэлбэрлүү хөрвүүлэх арга хайх хэрэгтэй.
Мод хадгалах нь нийтлэг алдаатай, олон шийдэлтэй байдаг. Энд 2 үндсэн арга байгаа: зэргэлдээ жагсаалтын модел, мөн дахин жагсаагдсан модны огтлолын алгоритм/the adjacency list model, and the modified preorder tree traversal algorithm./
Энэ сэдвээр бид, шаталсан өгөгдлийг хадгалах эдгээр 2 методыг үзнэ. Би жишээ болгож онлайн хүнсний дэлгүүрийн зохиомол модыг хэрэглэх болно. Энэ хүнсний дэлгүүр нь хүнсийг категориор, өнгөөр, төрлөөр нь зохион байгуулна. Мод нь иймэрхүү харагдана:

Энэ сэдвээр сэргээгдсэн өгөгдлийн хэрхэн хадгалах код-н жишээ байгаа. Би энэ хэлийг хэрэглэдэг, мөн маш олон өөр хүмүүс энэ хэлийг мэддэг учраас би PHP хэл дээр жишээгээ бичхээр сонгосон. Мэдээж та өөрийнхөө чаддаг хэлдээр үүнийг хөрвүүлж болно.
The Adjacency List Model
Эхний буюу гоёмсог нэг нь бидний зэргэлдээ жагсаалтын модел эсвэл рекурсив метод гэж нэрлэдэг методын үзье. Энэ нь маш гоёмсог байдаг, яагаад гэвэл та өөрийнхөө модонд давтагдах энгийн нэгхэн функцийг хэрэглэж болдог. Бидний хүнсний дэлгүүрийн хувьд бол тохируулсан хүснэгт маань доорх байдлаар харагдах болно:

Таны харж байгаагаар жагсаалтанд зангилаа болгон нь parent -тай байгаа харагдаж байна. Бид pear -г fruit эцэгтэй green -ны хүүхэд гэж харж байна. food нэртэй root зангилаа нь ямар нэгэн эцэггүй харагдаж байна. Хялбарчлахын тулд, би зангилаа бүрд title оруулж өгсөн байгаа. Мэдээж жинхэнэ өгөгдлийн санд бол та зангилаа бүр дээр тоон утга хэрэглэх хэрэгтэй.
Give Me the Tree
Одоо бид өгөгдлийн сандаа модоо оруулчлаа, одоо бол харагдах функцыг бичих цаг. Энэ функц нь root зангилаанаас эхлэх ёстой – зангилаа нь ямар ч эцэггүй – мөн энэ зангилааны бүх хүүхдийг дүрслэнэ. Эдгээр хүүхэд бүрд, тухайн хүүхдийн хүүхэд зангилаануудыг дүрслэнэ. Мөн эдгээр хүүхэд бүрд, тухайн хүүхдийн хүүхэд зангилаануудыг дүрслэнэ, гэх мэт явна.
Магадгүй чи анзаарсан байх, энэ бол энэ функцийг тайлбарлах зөв аргачлал гэдгийг. Бид тодорхой эцэг зангилааны хүүхдүүдийг сэргээх функцийг хялбараар бичиж чадна. Функц нь дараагаар нь өөрийнхөө хүүхдүүдийнх нь хүүхдүүдийг дүрслэх үйлдэлийг хийх хэрэгтэй. Энэ бол recursion method гэж нэрлэгдэх рекурсив механизм юм.
<?php <br>
// $parent is the parent of the children we want to see <br>
// $level is increased when we go deeper into the tree, <br>
// used to display a nice indented tree <br>
function display_children($parent, $level) { <br>
// retrieve all children of $parent <br>
$result = mysql_query(‘SELECT title FROM tree ‘. <br>
‘WHERE parent=”‘.$parent.’”;’); <br>
<br>
// display each child <br>
while ($row = mysql_fetch_array($result)) { <br>
// indent and display the title of this child <br>
echo str_repeat(‘ ‘,$level).$row['title'].”\n”; <br>
<br>
// call this function again to display this <br>
// child’s children <br>
display_children($row['title'], $level+1); <br>
} <br>
} <br>
?>
Бүтэн мод харуулахын тулд, бид функцыг $parent аргументийг хоосон, $level =0 гэж өгнө: display_children('',0);Бидний хүнсний дэлгүүрт функц нь дараах утга буцаана:
Food<br>
Fruit<br>
Red<br>
Cherry<br>
Yellow<br>
Banana<br>
Meat<br>
Beef<br>
Pork
Хэрэв та зүгээр дэд модноос эхэлж үзэхийг хүсэж байвал, функцд өөр зангилааг зааж өгнө. Жишээлбэл fruit дэд модны хувьд display_children('Fruit',0)
The Path to a Node
Бараг бүх ижил төрлийн функцнд хэрэв зөвхөн тухайн зангилааны нэр эсвэл, id -г мэдэж байвал зангилааны path-г олж тогтоох боломжтой байдаг. Үлгэрлэн хэлбэл’Cherry’ -н path нь ‘Food’ > ‘Fruit’ > ‘Red’. Энэ path -г олж тогтоохын тулд манай функц хамгийн гүн түвшин хүртэл явах хэрэгтэй. Энэ зангилааны эцгийг мэдээд үүнийгээ path-д нэмж өгнө. Бидний жишээнд энэ нь Red байна. Хэрэв бид Red -г эцэг гэдгийг мэдвэл бид түүнийгээ Cherry-гийн path-д Red гэж нэмж өгнө. Мөн бидний хэрэглэж байгаа функцийг рекурсиваар хэрэглэж ямар ч зангилааны path-г олж авна.
<?php <br>
// $node is the name of the node we want the path of <br>
function get_path($node) { <br>
// look up the parent of this node <br>
$result = mysql_query(‘SELECT parent FROM tree ‘. <br>
‘WHERE title=”‘.$node.’”;’); <br>
$row = mysql_fetch_array($result); <br>
<br>
// save the path in this array <br>
$path = array(); <br>
<br>
// only continue if this $node isn’t the root node <br>
// (that’s the node with no parent) <br>
if ($row['parent']!=”) { <br>
// the last part of the path to $node, is the name <br>
// of the parent of $node <br>
$path[] = $row['parent']; <br>
<br>
// we should add the path to the parent of this node <br>
// to the path <br>
$path = array_merge(get_path($row['parent']), $path); <br>
} <br>
<br>
// return the path <br>
return $path; <br>
} <br>
?>
Энэ функц нь одоо өгөгдсөн зангилааны path-г олох болно. Энэ функц нь path-г массив хэлбэрээр буцаана. Тэгэхээр бид path -г харуулахдаа print_r(get_path('Cherry')); -г хэрэглэж болно. Хэрэв бид ‘Cherry’-н хувьд бол, ингэж харагдах болно:
Array <br>
( <br>
[0] => Food <br>
[1] => Fruit <br>
[2] => Red <br>
)
Disadvantages
Бидний харснаар энэ бол гайхалтай метод. Хэрэглэхэд маш хялбар, мөн бидэнд хэрэгтэй код нь хэтэрхий энгийн. Тэгээд юу зэргэлдээ байх жагсаалтын моделуудын доод талд байна вэ? Ихэнх програмчлалын хэлэнд, энэ нь удаан, үр ашиггүй байдаг. Энэ нь ерөнхийдөө рекурсиваас болдог. Бидэнд модонд байх зангилаа болгонд нэг өгөгдлийн сангийн query бичих шаардлага тулгардаг.
Энэ нь query болгонд тодорхой хугацаа зарцуулдаг учир томоохон модны хувьд функц нь хэтэрхий удна.
Хоёрдох шалтгаан бол энэ метод нь магадгүй таны хэрэглэдэг програмын хэлэнд энэн шиг хурдан ажиллаж чадахгүй. Lisp гэх мэтээс ондоо ихэнх програмын хэлэнд рекурсив функц загварчлагдаагүй байдаг. Зангилаа бүрд функц нь өөрийнхөө адил үүсгэж эхлүүлдэг. Тиймд 4 түвшиний хувьд, ижил хугацаанд 4 функцын 4 хуулбар ажиллах болно. Функц бүр нь санах ойн хэсгийг эзэлж мөн эхлэхдээ тодорхой хугацааг авна, рекурсив бол том модны хувьд бол маш удаан ажиллах юм.
Modified Preorder Tree Traversal
Одоо өөр төрлийн мод хадгалах функцийн талаар үзье. Рекурсив бол удаан байна, тийм учир бид үнэндээ бол рекурсив функцийг хэрэглэхгүй юм. Бид мөн SQL query-ны тоог багасгах зорилт тавьна. Бид нэг активитид нэг SQL query бичих зарчимыг эрхэмлэх хэрэгтэй.
Бид өөрсдийн модоо хэвтээ чиглэлд дүрслэх хэрэгтэй. root зангилаа (‘Food’) -с эхэлж, түүний зүүн талд 1-н тоо тавина. ‘Fruit’ нэртэй модонд мөн адилханаар хийж 2-н тоо хажууд нь тавиарай. Яаг энэ зарчимаар цааш үргэлжлүүлж модны төгсгөл хүртэл зангилаа бүрийн баруун, зүүн талд тоо тавина. Хамгийн сүүлийн дугаар нь ‘Food’ зангилааны баруун талд тавигдах болно. Доорх зурганд та бүтэн дугаарлагдсан модыг харж байна. Мөн дугаарын чиглэл заасан хэдэн сумны хамтаар.

Бид эдгээр дугааруудыг баруун, зүүн гэж ангилж дуудна. Жишээлбэл ‘Food’ зангилааны хувьд зүүн утга нь 1, баруун утга нь 18 юм. Таны ойлгосноор эдгээр дугаарууд нь зангилаан бүрийн хамаарлыг тэмдэглэх юм. ‘Red’ нь 3, 6 гэсэн дугаартай тул 1, 18 дугаартай ‘Food’ зангилааны удам юм. Яаг энэ зарчимаар бид 2-11 ‘Fruit’ зангилааны удам зангилаануудын зүүн утгууд нь 2 -с их, харин баруун утгууд нь 11-с бага байна гэдгийг харж байна. Модны бүтэц нь одоо зүүн, баруун дугааруудад хадгалагдсан бүтэцтэй байна. Энэхүү модны эргэн тойронгоор явдаг болон зангилаа бүрийг тоолдог методыг ‘modified preorder tree traversal’ алгоритм гэж нэрлэдэг.
Цааш үргэлжлүүлэхийн өмнө бид дээрх модны дугаарууд нь хүснэгтэнд хэрхэн дүрслэгдсэнгийг харъя.

Баруун, зүүн гэдэг үгнүүд нь SQL бичихэд чухал үүрэгтэй оролцоно гэдгийг анхаараарай. Тийм учраас бид ‘lft’ болон ‘rgt’ -г багануудыг тодорхойлоход хэрэглэх болно. Мөн бид цаашид дахин эцэг багана гэдгийг хэрэглэхгүй болсон гэдгийг анхаараарай. Бид одоо модны бүтцийг хадгалахын тулд ‘lft’ болон ‘rgt’ утгуудтай болсон.
Модны утгыг дуудах
Хэрэв та ‘lft’ болон ‘rgt’ утгуудаар модыг дуудаж үзүүлэх гэж байгаа бол та дуудах гэж байгаа зангилаагаа эхлээд тодорхойлох хэрэгтэй. Жишээлбэл та ‘Fruit’ дэд модыг үзүүлэх гэж байгаа бол, та зөвхөн 2 болон 11 утгуудын хоорондох зүүн дугаартай зангилаануудыг дуудах хэрэгтэй. SQL нь дараах байдалтай байна:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;
Энэ нь дараахыг буцаана:

Тэгэхээр энд бүтэн мод ганцхан query-д орсон байна. Бид рекурсив функцийн тусламжтайгаар дүрсэлж байсанаар модыг үзүүлэхийг тулд бид энэ query-нд ORDER BY заалтыг тавьж өгөх хэрэгтэй. Хэрэв та хүснэгтээс бичлэг устгах юмуу эсвэл бичлэг нэмэх бол, магадгүй таны хүснэгтийн зөв бүтэц нь алдагдах юм. Бид тийм учир зүүн дугаараар бичлэгүүдийг эрэмбэлж байна.
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
Зөвхөн жагсааж харуулах нь асуудал болж үлдлээ.
Модны бүтцийг үзүүлэхийн тулд, хүүхдүүд нь эцгээсээ илүү хялбарханаар жагсагдсан байх хэрэгтэй. Бид баруун дугааруудын багцыг хадгалж үүнийг хийнэ. Зангилааны хүүхдүүдийг эхлүүлэх бүртээ, та зангилааны баруун дугааруудыг багруугаа нэмнэ. Та зангилааны хүүхэд бүрийн баруун дугаарууд түүний эцэг зангилааны баруун утгаас бага гэдгийг мэдэж байгаа, тэгэхээр тухайн очсон байгаа зангилааны баруун утгыг багцанд байх хамгийн сүүлийн зангилааны баруун утгатай харьцуулж үзвэл, та эндээс урдын адил эцэг зангилааны хүүхдүүдийг дүрсэлж болохыг харж болно. Та зангилааг дүрсэлж үзүүлсэн үедээ түүний баруун утгыг багцаас устга. Хэрэв та багцанд байх элэментүүдийг тоолвол, та тухайн зангилааны түвшинг олж авах болно.
<?php <br>
function display_tree($root) { <br>
// retrieve the left and right value of the $root node <br>
$result = mysql_query(‘SELECT lft, rgt FROM tree ‘. <br>
‘WHERE title=”‘.$root.’”;’); <br>
$row = mysql_fetch_array($result); <br>
<br>
// start with an empty $right stack <br>
$right = array(); <br>
<br>
// now, retrieve all descendants of the $root node <br>
$result = mysql_query(‘SELECT title, lft, rgt FROM tree ‘. <br>
‘WHERE lft BETWEEN ‘.$row['lft'].’ AND ‘. <br>
$row['rgt'].’ ORDER BY lft ASC;’); <br>
<br>
// display each row <br>
while ($row = mysql_fetch_array($result)) { <br>
// only check stack if there is one <br>
if (count($right)>0) { <br>
// check if we should remove a node from the stack <br>
while ($right[count($right)-1]<$row['rgt']) { <br>
array_pop($right); <br>
} <br>
} <br>
<br>
// display indented node title <br>
echo str_repeat(‘ ’,count($right)).$row['title'].”\n”; <br>
<br>
// add this node to the stack <br>
$right[] = $row['rgt']; <br>
} <br>
} <br>
?>
Хэрэв та энэ кодыг ажиллуулвал, бидний өмнө нь рекурсив функцээр хийж байсан модтой адилхан модыг авчирч чадна. Бидний шинэ функц магадгүй илүү хурдан болох байх: Энэ бол рекурсив биш бөгөөд зөвхөн 2 query -г хэрэглэж байна.
Зангилаанд хүрэх зам
Энэ шинэ алгоритмаар, бид мөн тодорхойлогдсон зангилааны замыг олж авах шинэ арга олох ёстой. Энэ замыг авахын тулд, бид тухайн зангилааны өвгүүдийн жагсаалтыг олох хэрэгтэй.
Бидний хүснэгтийн шинэ бүтцээр бол энэ нь их ажил удахгүй хийгдэнэ. Бид жишээ болгож 4-5 ‘Cherry’ зангилааг авч үзэх юм бол, түүний бүх өвгүүдийн зүүн дугаарууд нь 4 -с бага, бүх баруун дугаарууд нь 5-с их байна гэдгийг харж байна. Бүх өвгүүдийг олж авчрахын тулд, бид дараах query-г ажиллуулна:
SELECT title FROM tree WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC;
Өмнөх Query-нд хэрэглэж байсан шиг ORDER BY заалтыг хэрэглэж зангилааг эрэмбэлнэ гэдгийг анхаараарай. Энэ Query дараах үр дүнг буцаана:
+——-+<br>
| title |<br>
+——-+<br>
| Food |<br>
| Fruit |<br>
| Red |<br>
+——-+
Одоо бидэнд ‘Cherry’ зангилааны замаас ирэх бичлэгүүдлүү хандах боломжтой боллоо.
Хэдэн ширхэг үр удам байна вэ
Хэрэв та надад зангилааны баруун, зүүн дугааруудыг өгвөл, би бяцхан математик тооцоогоор хэдэн ширхэг үр удам зангилаа байгааг хэлж өгч чадна.
Үр удам бүрийн хувьд зангилааны баруун дугаарууд нь 2 -р нэмэгдсэн байна, үр удмын тоо дараах тооцооллоор бодогдоно:
descendants = (right – left - 1) / 2
Энэ энгийн томъёогоор, би таньд 2-11 ‘Fruit’ зангилаа нь 4 ширхэг үр удам зангилаатай бөгөөд 8-9 ‘Banana’ нь зүгээр хүүхэд зангилаа, эцэг биш гэдгийг хэлж чадна.
Automating the Tree Traversal
Та энэхүү хүснэгтэнд хийж чадах зүйлсийн зарим нэгийг нь үзэж танилцлаа, одоо та хүснэгтийг хэрхэн автоматаар үүсгэх талаар сурах болно. Энэ нь жижиг модны хувьд эхний удаад ажиллахад маш сайхан дасгал байсан ч, бидэнд модны дагуу явж үүнийг бүгдийг нь тоолох тийм скрипт нь маш их хэрэг болох юм.
Зэргэлдээ жагсаалтыг modified preorder tree traversal хүснэгтрүү хөрвүүлдэг скрипт бичицгээе.
<?php <br>
function rebuild_tree($parent, $left) { <br>
// the right value of this node is the left value + 1 <br>
$right = $left+1; <br>
<br>
// get all children of this node <br>
$result = mysql_query(‘SELECT title FROM tree ‘. <br>
‘WHERE parent=”‘.$parent.’”;’); <br>
while ($row = mysql_fetch_array($result)) { <br>
// recursive execution of this function for each <br>
// child of this node <br>
// $right is the current right value, which is <br>
// incremented by the rebuild_tree function <br>
$right = rebuild_tree($row['title'], $right); <br>
} <br>
<br>
// we’ve got the left value, and now that we’ve processed <br>
// the children of this node we also know the right value <br>
mysql_query(‘UPDATE tree SET lft=’.$left.’, rgt=’. <br>
$right.’ WHERE title=”‘.$parent.’”;’); <br>
<br>
// return the right value of this node + 1 <br>
return $right+1; <br>
} <br>
?>
Энэ бол рекурсив функц. Та rebuild_tree(‘Food’,1); гэж үүнийг ажиллуулна. Функц нь ‘Food’ зангилааны бүх хүүхдүүдийг дуудна.
Хэрэв энд ямар нэгэн хүүхэд байхгүй бол, энэ нь өөрийнхөө зүүн болон баруун утгуудыг зааж өгнө. Зүүн утга нь 1 гэж өгөгдөөд, баруун утга нь нэгээр нэмэгдүүлж өгнө. Хэрэв хүүхэд байвал, энэ функц нь дахин дуудагдах бөгөөд хамгийн сүүлийн баруун утгыг буцаана. Тэрхүү утга нь ‘Food’ зангилааны баруун утгаар хэрэглэгдэнэ.
Рекурсив нь модыг ойлгогдохоор зохистой хэлбэрлүү оруулж өгдөг. Хэдий тийм боловч, энэхүү функц нь бидний эхэн хэсэгт гараар хийж байсан үйлдэлтэй ижилхэн үр дүнг хийж гүйцэтгэнэ. Энэ нь модны эргэн тойрон дагуу явж хүрсэн зангилаа бүртээ нэгийг нэмж өгч байгаа. Энэ функцийг ажиллуусаны дараагаар, зүүн баруун дугаарууд хэвэндээ байхыг олж харна. (хурдан шалгах: root зангилааны баруун утга нь нийт зангилаааны тооноос 2 дахин их байна.)
Зангилаа нэмэх:
Бид модонд зангилаа хэрхэн нэмэх вэ? Үүнийг хийх 2 арга зам байна: Та хүснэгтэндээ эцэг зангилааны утгыг хадгалах баганыг хадгалж дараа нь rebuild_tree() функцийг дахин ажиллуулаад болоо - хялбархан боловч тийм ч гоёмсог функц биш; Эсвэл шинээр орсон зангилааны баруун талын бүх зангилааны баруун, зүүн утгуудыг дахин засварлах арга байна.
Эхний сонголт бол хялбархан. Засвар хийхийн тулд жагсаах методтой нөхөрлөх болж байна. мөн сэргээлтийн modified preorder tree traversal algorithm ажиллаж байна. Хэрвээ та шинэ зангилаа нэмхийг хүсвэл, та үүнийгээ хүснэгтээ нэмж өгөөд эцэг зангилааг нь зааж өгөх болно. Тэгээд та rebuild_tree() функцийг хялбарханаар дахин ажиллуулна. Энэ бол хялбар арга юм. Гэхдээ том модны хувьд бол бүтээмж муутай болно.
2 дахь зангилааг нэмэх болон устгах арга бол шинээр нэмэгдэж байгаа зангилааны баруун талын бүх зангилааны баруун зүүн утгуудыг дахин засварлах юм. Үүнийг жишээн дээр харцгаая. Бид ‘Strawberry’ нэрийн жимсний шинэ төрлийг ‘Red’ зангилааны төгсгөл болгож хүүхдээр нэмхийг хүсч байна, Эхлээд бид хоосон зай үүсгэх ёстой. ‘Red’ -н баруун утга нь 6 -с 8 болж 7-10 ‘Yellow’ зангилаа нь 9-12 болно гэх мэт явна. ‘Red’ зангилаанд засвар оруулна гэдэг нь бид 5 -с их утгатай бүх зангилааны баруун зүүн утгуудыг 2 -р нэмэгдүүлнэ гэсэн үг.
Бид энэхүү query-г хэрэглэх болно:
UPDATE tree SET rgt=rgt+2 WHERE rgt>5; <br>
UPDATE tree SET lft=lft+2 WHERE lft>5;
Одоо бид шинэ зайг бөглөх ‘Strawberry’ зангилааг нэмж болно. Энэхүү зангилаа нь зүүн нь 6, баруун нь 7 байна.
INSERT INTO tree SET lft=6, rgt=7, title=’Strawberry’;
Хэрэв бид display_tree() функцийг ажиллуулж үзвэл ‘Strawberry’ зангилаа модонд орсон байхыг олж харна.
Food <br>
Fruit <br>
Red <br>
Cherry <br>
Strawberry <br>
Yellow <br>
Banana <br>
Meat <br>
Beef <br>
Pork
Дутагдалтай талууд
Энэхүү аргыг ойлгоход эхэндээ хүнд санагдах болно. Энэ нь The Adjacency List Model-г бодвол тийм ч хялбар биш юм. Та нэг удаа л баруун, зүүн утгуудыг оруулаад өгчих юм бол, The Adjacency List Model-ний хийж байсан бүх үйлдэлийг үүгээрээ хийж чадах бөгөөд энэ нь маш хурдан ажиллах модел юм. Модыг шинэчлэх хэсэгтээ бол илүү их query бичиж жаахан удах боловч, дуудахдаа ганцхан query-гээр хурдтай дуудаж чадна.
Дүгнэлт
Та одоо модыг дүрслэх 2 аргатай танилцлаа. Миний хувьд modified preorder tree traversal-г илүү дээр сонголт гэсэн үзэлтэй байгаа хэдий ч, та тухайн хэрэгцээнд adjacency list method нь илүү дээр хэрэглэгдэх тохиолдол байж болох байхаа. Энэ сонголт хийх асуудлыг таньд өөрт тань үлдээе.
Хамгийн сүүлийн тайлбар: Миний хэлсэнээр та модны түлхүүр үг болгож гарчигаар дуудас шаардлагагүй. Та бол өгөгдлийн сангийн нормализашны үндсэн дүрмийг л баримталж юмаа хийх хэрэгтэй. Миний хувьд жишээн дээр харуулахад илүү хялбар байлгах үүднээс л түлхүүр талбартаа тоон утга хэрэглээгүй болно.
Илүү их мэдлэгийг эндээс:
More on Trees in SQL by database wizard Joe Celko:
http://searchdatabase.techtarget.com/tip/1,289483,sid13_gci537290,00.html
Two other ways to handle hierarchical data:
http://www.evolt.org/article/Four_ways_to_work_with_hierarchical_data/17/4047/index.html
Xindice, the ‘native XML database’:
http://xml.apache.org/xindice/
An explanation of recursion:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_9_5.html
adjacency list method