Вывод дерева mysql

291
02 июня 2017, 12:05

Есть таблица elements следующей структуры Adjacency List Model:

id parent index

Где 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. Менять в структуре, к сожалению, ничего нельзя

Заранее спасибо

Answer 1

В MySQL нет штатных средств для работы с рекурсивными запросами. Но как известно, если очень хочется, то можно (хотя выглядит это жутковато и оптимизации по скорости это не поддается):

select id,path
  from (
   select  @path:=if(@id!=id,`index`,
             coalesce(
               (select concat(`index`,'/',@path)
                  from Tree1 where id=@pid)
             ,@path)
           ) path,
           @pid:=if(@id!=id,parent,
             (select parent from Tree1 N
               where id=@pid)
             ),
            @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) и отсортировать по пути индексов.

Answer 2

Чтобы вывести полный путь в одном запросе нужно использовать Nested Set Model. (Полная информация по ссылке)

Для построения пути можно использовать хранимую функцию. При процедурном языке мы можем начать в нижней части дерева и перебирать вверх, чтобы вернуть полное дерево или единственный путь.

https://web.archive.org/web/20110606032941/http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

READ ALSO
Оставить в БД только n записей

Оставить в БД только n записей

ЗдравствуйтеЗадание такое: в базе должно храниться не более 12 записей

352
Java SE, DAO, MySql, Swing

Java SE, DAO, MySql, Swing

Всем приветДелаю дэскттопное приложение на виндоус 10 на старой библиотеке SWING

292
sql запрос в базу данных

sql запрос в базу данных

Допустим, есть таблица:

236
Создание CMS на php [требует правки]

Создание CMS на php [требует правки]

Здравствуйте! Нужно создать небольшое CMS, только пока не могу понять все аспектыПонимаю что можно создать панель администратора и через него...

296