Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
WITH RECURSIVE tree AS (
SELECT
id, short_name, parent_id, short_name AS sort_string, 1 AS depth
FROM stations
WHERE parent_id IS NULL
UNION ALL
SELECT
s1.id, s1.short_name, s1.parent_id,
tree.sort_string || '|' || s1.short_name AS sort_string, tree.depth+1 AS depth
FROM
tree
JOIN stations s1 ON s1.parent_id = tree.id
)
SELECT depth, short_name, id, parent_id, sort_string FROM tree ORDER BY sort_string ASC;
insert into stations
values
(1, 'name', null),
(2, 'name|0', null),
(3, 'name|1', null),
(4, 'name0', null),
(5, '1', 1),
(6, '2', 2),
(7, '3', 3);
insert into stations
values
(11, 'name', null),
(12, 'name2', null),
(13, 'name3', null),
(14, 'name4', null),
(15, '1', 11),
(16, '2', 12),
(17, '3', 13);
WITH RECURSIVE r AS (
SELECT id, parent_id, name
FROM tmp.geo
WHERE parent_id = 4
UNION all
select *
from
(
with rr as
(
select * from r
)
SELECT id, parent_id, name
FROM tmp.geo
WHERE parent_id IN ( SELECT id FROM rr )
) a
)
SELECT * FROM r;
</source lang>
Часто использую recursive для быстрых выборок по индексу. Получается трудно читаемо, но очень быстро.WITH RECURSIVE
tree_query_1 AS (... --рекурсивный запрос
UNION ALL...
),
tree_query_2 AS (... --рекурсивный запрос
UNION ALL...
),
simple_query_1 AS (... --нерекурсивный запрос
--no UNION
)
--далее строим отчёт, используя объявленные выше запросы
SELECT
t1.field1,
(SELECT field2 FROM simple_query_1 WHERE id = t1.field2) --используем в блоке SELECT
FROM table_1 t1
INNER JOIN tree_query_1 t2 ON t1.field3 = t2.field4 --используем в JOIN
LEFT JOIN (SELECT * FROM tree_query_2 WHERE...) -- используем в подзапросе в JOIN
Большущее всем спасибо за простые пояснения. Теперь ясно, что в Postgres есть цикл while с условием :) Пригодилось только что для построения кучки деревьев с убиранием циклических зависимостей и прочими радостями.
Рекурсивные запросы в PostgreSQL (WITH RECURSIVE)