Mysql дерево одним запросом

Вывод дерева 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);

В принципе вот и все. Согласитесь что несложно, а времени скрипта экономится , дай БожЕ. И применений куча. Так что считай что если ты прочитал и вник первый раз, то жму руки а сам сваливаю до дому.

Источник

Оцените статью