Ответ
Да, PostgreSQL поддерживает рекурсивные запросы с помощью конструкции WITH RECURSIVE
.
Они незаменимы для работы с иерархическими или графовыми структурами данных, такими как:
- Организационная структура компании (менеджеры и подчиненные).
- Дерево категорий в интернет-магазине.
- Социальные связи (поиск друзей друзей).
- Маршруты в транспортной сети.
Структура рекурсивного запроса
Запрос состоит из двух частей, объединенных через UNION ALL
:
- Начальная (anchor) часть: Нерекурсивный
SELECT
, который выполняется один раз и формирует стартовый набор данных. - Рекурсивная часть:
SELECT
, который ссылается на сам себя (на имя CTE) и выполняется до тех пор, пока возвращает непустой результат.
Пример: поиск всех подчиненных для заданного руководителя
WITH RECURSIVE subordinates AS (
-- 1. Начальная часть: находим прямых подчиненных руководителя с id = 1
SELECT id, name, manager_id
FROM employees
WHERE manager_id = 1
UNION ALL
-- 2. Рекурсивная часть: присоединяем сотрудников, чей manager_id
-- совпадает с id сотрудника из предыдущего шага
SELECT e.id, e.name, e.manager_id
FROM employees e
INNER JOIN subordinates s ON s.id = e.manager_id
)
SELECT * FROM subordinates;
Важные моменты:
- Условие завершения: Рекурсия прекращается, когда рекурсивная часть перестает возвращать новые строки. Крайне важно правильно составить условие объединения, чтобы избежать бесконечного цикла.
- Производительность: На очень глубоких или широких иерархиях рекурсивные запросы могут быть медленными. В таких случаях стоит рассмотреть альтернативные способы хранения иерархии (например,
ltree
илиMaterialized Path
).