Вывод дерева mysql
Где index — это порядок элемента. Нужно одним запросом сформировать путь, получающийся при обходе в глубину. То есть если у нас такой вид:
1 0 1 2 0 2 3 1 1 4 1 2 5 2 1 6 0 3
То выведется 1 3 4 2 5 6 Нужно на чистом mysql без использования php и тд. Заранее спасибо P.S. Менять в структуре, к сожалению, ничего нельзя Заранее спасибо
В PostgreSQL поддерживаются рекурсивные запросы WITH RECURSIVE, а в Oracle иерархические запросы (hierarchical query clause (also known as “CONNECT BY query”) or recursive subquery factoring).
MySQL не поддерживает рекурсивных запросов. А потому вариантов два. Первый — создание хранимой процедуры, которая отдаст требуемые данные. Второй — создание дополнительной таблицы, в которой будут храниться преобразованные из исходного вида данные в удобном для решения поставленной задачи формате плюс код (триггер и/или эвент), актуализирующий эту таблицу при внесении изменений в исходную.
2 ответа 2
В MySQL нет штатных средств для работы с рекурсивными запросами. Но как известно, если очень хочется, то можно (хотя выглядит это жутковато и оптимизации по скорости это не поддается):
select id,path from ( select @path:=if(@id!=id,`index`, coalesce( (select concat(`index`,'/',@path) from Tree1 where ,@path) ) path, @pid:=if(@id!=id,parent, (select parent from Tree1 N where ), @id:=id id, N from Tree1 T, (select @n:=@n+1 N from Tree1,(select @n:=0) N limit 3) Seq, (select @id:=0,@path:='') X order by id, N ) X where N=3 order by path
Так как ни рекурсии ни циклов в обычном смысле слов нет, то запрос эмулирует рекурсию с помощью эмуляции цикла. В качестве цикла используется склейка с любой таблицей, в которой записей не менее, чем максимально возможный уровень иерархии в дереве. В данном примере используется выборка из той же самой таблицы, явно ограниченная limit 3 (если вложенность дерева больше — число надо соответственно увеличить). Собственно данные из этой таблицы не берутся, а создаются порядковые номера ( N ).
После этой склейки у нас в выборке появляется по 3 записи с одним и тем же id. На каждой из них, с помощью переменных, мы получаем id очередной родительской ветки, углубляясь по дереву (так как переменные помнят значения, сформированные в предыдущей строке). Самое главное, что мы тут формируем это путь к данной записи в виде индексов сортировки (если index может быть более 9 то для правильной сортировки надо выравнивать его в пути до одинаковой длины с помощью lpad() )
В какой то момент записи родителей заканчиваются, мы дошли до корня дерева, тогда подзапрос индекса родителя возвращает NULL и при этом с помощью coalesce мы сохраняем ранее сформированный путь. Таким образом в последней записи нашего «цикла» у нас гарантированно будет полный путь до данного листа дерева. Нам остается только убрать из выборки рабочие строки цикла с частично сформированными путями, т.е. выбрать только последние строки ( where N=3 ) и отсортировать по пути индексов.
Источник
Вывод дерева в MySQL
Данная тема уже заезжена до протертых шин, но все таки какой программист с этим не сталкивался. Я лишь покажу один пример, основанный на базе, рекурсия с выполнением каждого раза запроса может оказаться ненароком очень долгой, поэтому сначала забросим все данные одним запросом в массив, а рекурсией будем пробегаться по нему.
Понеслася.
Определимся с чем будем иметь дело. Примерная табла будет содержать как минимум 3 столбца.
CREATE TABLE Tree ( `ID` INT NOT NULL AUTO_INCREMENT, `ParentID` INT NOT NULL, `Title` VARCHAR(255) NOT NULL, PRIMARY KEY(`ID`) )
Ну и что нам теперь делать? Осталось написать скрипт который бы обработал эту таблицу и вывел дерево на экран. Как и было сказано, для начала надо выполнить запрос на всю базу.
SELECT ID, ParentID, Title FROM Tree;
Результат собираем следующим образом. Если вы представляете себе двухмерный массив то без труда поймете следующий код.
while($row = mysql_fetch_assoc($res))
Чтобы посмотреть что же лежит в массиве можно просто выполнить print_r($tree) и будет вам счастье! Для чего я заделал $row[‘ID’] на второй уровень? Для связи с ParentID, действуем таже как если бы мы просто выполняли запросы в рекурсии, но мы же орудуем массивами.
Step By Step
Я пробегаюсь по всему Parent дереву. Если помните то в $root будет содержаться массив с содержимым всех полей с этим ParentID. Чтобы не повторится с выводом полей сделаем затычку $pid!=$id для следующего вызова рекурсии. Осталось лишь пробежаться по содержимому, для чего запускаем второй foreach. Немного отступлюсь. чтобы не было недоразумений, типа а чего скрипт ругается на foreach, прямо перед ним делаю проверку на количество содержимого массива. Естественно, foreach обрабатывает массив и к тому же не «нулевый»!
Возвращаемся.
Именно во втором цикле надо вызывать рекурсию, для чего сначала проверим , а есть ли потомки с таким родителем.
if(count($tree[$key]))ShowTree($tree,$key);
В принципе вот и все. Согласитесь что несложно, а времени скрипта экономится , дай БожЕ. И применений куча. Так что считай что если ты прочитал и вник первый раз, то жму руки а сам сваливаю до дому.
Источник