Postgresql рекурсивный запрос дерево

Рекурсивный запрос на postgres

Когда различные иерархии находятся в пределах одной таблицы, может потребоваться пройтись по одной из веток этой иерархии, начиная с самого нижнего элемента и заканчивая корневым. Примером иерархических данных может служить структура каталогов на файловой системе, оргструктура в компании или справочник географических объектов (города-страны-континенты).

PostgreSQL предоставляет специальный синтаксис with recursive для написания рекурсивных запросов. Эти запросы позволяют легко выбирать иерархические данные.

Данный гайд также доступен в формате видео на YouTube.

Рассмотрим конкретную таблицу:

create table hierarchy_example (
id serial not null ,
name character varying ( 100 ),
parent_id integer ,
constraint id_pk primary key (id)
)

Здесь поле parent_id содержит номер записи, которая является родительской по отношению к данной. Если parent_id = null, считаем, что это – корневой элемент иерархии.

insert into hierarchy_example (name, parent_id) values ( ‘root’ , null );
insert into hierarchy_example (name, parent_id) values ( ‘item1’ , 1 );
insert into hierarchy_example (name, parent_id) values ( ‘item2’ , 1 );
insert into hierarchy_example (name, parent_id) values ( ‘subitem1’ , 2 );

Теперь составим запрос для прохода по этой иерархии, от элемента с именем subitem1 до root. На каждой итерации будем добавлять новую строку во временную таблицу temp1.

with recursive temp1 (id, parent_id, name, path) as (
select t1.id, t1.parent_id, t1.name, cast (t1.name as varchar ( 50 )) as path
from hierarchy_example t1 where t1.name = ‘subitem1’
union
select t2.id, t2.parent_id, t2.name, cast (temp1.path || ‘->’ || t2.name as varchar ( 50 ))
from hierarchy_example t2 inner join temp1 on (temp1.parent_id = t2.id))
select * from temp1

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

Читайте также:  Кресло качалка дерево ручная работа

Внутри рекурсивный запрос (то, что записано в скобках после ключевого слова as) можно разделить на две части, которые объединены ключевым словом union. Первая часть – это запрос для поиска элемента, с которого следует начать рекурсивный запрос. Вторая часть – то, что выполняется в каждой итерации. Здесь мы выбираем номер элемента, номер его родительского элемента, а также для наглядности определяем временную переменную path, в которой будет содержаться пройденный путь по иерархии.

В самом конце следует обычный запрос, который выполняется к временной таблице temp1, в которую мы помещали строки в каждой итерации.

Результат выполнения запроса:

id parent_id name path
4 2 subitem1 subitem1
2 1 item1 subitem1->item1
1 root subitem1->item1->root

Как видим, в столбце path последовательно отображается путь от subitem1 до root. Также обратите внимание, что в столбце name нет элемента item2 – он не входит в данную ветвь иерархии.

Источник

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