Общие > Базы данных
Запрос запроса запроса...
Mrh:
Казалась бы простая задача.
База:
ID, Parent_ID, Name
Это таблица с деревом каталогов. Родитель наивысшего уровня имеет Parent_ID = 0 соответственно... Глубина - любая.
Нужно "развернуть" полную структуру каталогов, к примеру:
--- Код: ---
Рыбы
Рыбы -> Тропические
Рыбы -> Глубоководные
Рыбы -> Глубоководные -> C ушами
Рыбы -> Глубоководные -> В полушубке
Рыбы -> Глубоководные -> Без глаз
Звери
Звери -> Дикие
--- Конец кода ---
...
Но возникла грабля, поскольку глубина любая (к примеру PHP):
$ID_Start = 0;
$sectQuery = "SELECT ID,Name FROM section WHERE Parent_ID = \'$ID_Start\'";
$sectResult = MySQL_Query ($sectQuery);
echo "<select name=ID>\\n";
while (list ($ID_Start,$Name) = MySQL_Fetch_Row ($sectResult)):
echo "<option value=$ID_Start>$Name\\n";
//Тут бесконечная вставка - "отлистыватель"
... Каков алгоритм, чтобы не нужно было делать бесконечную вставку?
Макс:
Почему вставка бесконечная, она ведь равна количеству разделов в таблице.
--- Цитировать ---Казалась бы простая задача.
--- Конец цитаты ---
Для мускуля дерево - задача не такая уж простая (ИМХО).
Первое что приходит в голову - примерно так:
1.Формируешь SQL-запрос так, что бы сразу у тебя все эаписи были в необходимом порядке. (ID и ParentID для этого недостаточно ИМХО).
2. Собираешь в массив строки, к которым может быть присоединена текущая строка (его постоянно прийдется менять).
К примеру перед обработкой строки N6 твоего примера ("Без глаз") в массиве должны быть три строки (Рыбы | Глубоководные | В полушубке ) а после ее обработки в массиве уже должно быть (Рыбы | Глубоководные | без глаз )
Короче, если ты ничего не понял и если никто ничего более понятного не предложит - пиши, буду разжевывать (а то сам понимаю, а популярно объяснить - проблема) :(.
Боря Елкин:
Если дерево, то это рекурсия. Я уже приводил пример обхода http://forums.webscript.ru/showthread.php?s=&postid=17691#post17691 каталога, сейчас попробуем адаптировать к обходу дерева на mysql.
PHP не знаю, нарисую смесь Perl и ПХП.
sub readdirs #читаем дерево каталога
{
$ID_Start=shift;
$In_Name=shift;
my $ret;
$sectQuery = "SELECT ID,Name FROM section WHERE Parent_ID = \'$ID_Start\'";
$sectResult = MySQL_Query ($sectQuery);
return if !$sectResult;
while (list ($ID_Start,$Name) = MySQL_Fetch_Row ($sectResult)){
$ret.="$In_Name -> $Name\\n";
$ret.=readdirs($ID,"$In_Name -> $Name");
}
return $ret;
}
Алгоритм примерно такой.
Макс:
--- Цитировать ---Если дерево, то это рекурсия.
--- Конец цитаты ---
Не обязательно.
Можно и одним select-ом дерево вытаскивать. На phpclub мне посоветовали алгоритм "Nested Sets" (вроде так называется) но я его пока не использовал и не разбирался.
В фидо как-то один парень предложил такой алгоритм:
Ввести в таблицу поле (назову его Number) и это поле будет порядковым номером данного элемента в дереве. И сортируя по number получаем на выходе дерево. А при вставке нового элемента в середину дерева все элементы которые будут ниже его изменяют свой number на +1.
Недостаток - тормоза при добавлении элемента в дерево. У меня получилось 2-4 запроса к БД при добавлении элемента.
Боря Елкин:
ОК, тебе лучше знать, я всего лишь предложил тебе рабочий вариант решения.
Навигация
Перейти к полной версии