Вы не можете сделать это только с SQL-запросами (по крайней мере, в MySQL). Один из подходов с SQL и PHP заключается в следующем:
SELECT id, IFNULL(parent_id, 0) AS parentid, chapter FROM toc ORDER BY parentid, display_order
Затем вы читаете этот набор строк в массив $ a следующим образом:
while ($row = mysql_fetch_array($result)) {
$a[$row['id']]['name'] = $row['chapter'];
$a[$row['parentid']]['children'][] = $row['id'];
}
Будет создан фиктивный элемент с первым индексом 0.
Небольшая примерная функция для печати отступа для заданного уровня (вы можете использовать CSS с отступом вместо или любым другим способом генерирования отступа):
function printIndent($level = 0) {
for ($j = 0; $j <= $level; $j++) echo ' ';
}
Затем вы создаете рекурсивную функцию printTree, которая выводит дерево:
function printTree($key = 0, $level = 0) {
if ($key > 0) {
printIndent($level);
echo $a[$key]['name'];
}
if (count($a[$key]['children'])
foreach ($a[$key]['children'] as $child)
printTree($child, $level + 1);
}
и вы звоните один раз с:
printTree();
Вот и все. Обратите внимание, что я пропустил инициализацию массива и не запускал этот пример кода, поэтому он может иметь синтаксическую ошибку, но принцип таков.
Недостаток этого подхода заключается в том, что если у вас есть очень большое количество элементов, это не будет наиболее эффективным, поскольку вы сначала читаете все сразу в большой массив. Но для меньшего количества предметов это хорошее решение.