Справочник по функциям

WITH

Конструкция SQL

Задаёт именованный подзапрос (общее табличное выражение, CTE), к которому основной запрос обращается как к таблице.

PostgreSQL 17.5
WITH [RECURSIVE] name_cte [(column[, ...])] AS (subquery) main_query

Параметры

RECURSIVEключевое словонеобязательный
Разрешает табличному выражению ссылаться на само себя
name_cteимя
Имя табличного выражения
columnимянеобязательный
Имена столбцов табличного выражения, по умолчанию берутся из subquery
subqueryподзапрос
Подзапрос, результат которого доступен по имени name_cte
main_queryподзапрос
Основной запрос, который обращается к name_cte как к таблице

Возвращаемое значение

Временная именованная выборка, доступная только в этом запросе

Примеры

Статусы, где больше одного человека

PostgreSQL 17.5
WITH status_counts AS (
	SELECT status,
		COUNT(*) AS members_count
	FROM FamilyMembers
	GROUP BY status
)
SELECT status,
	members_count
FROM status_counts
WHERE members_count > 1
ORDER BY status;
statusmembers_count
daughter3
father2
mother2

Числа от 1 до 5 через RECURSIVE

PostgreSQL 17.5
WITH RECURSIVE numbers (n) AS (
	SELECT 1
	UNION ALL
	SELECT n + 1
	FROM numbers
	WHERE n < 5
)
SELECT n
FROM numbers;
n
1
2
3
4
5

Подчинённые руководителей по уровням

PostgreSQL 17.5
WITH RECURSIVE subordinates AS (
	SELECT id,
		name,
		manager_id,
		1 AS LEVEL
	FROM employees
	WHERE manager_id IS NULL
	UNION ALL
	SELECT e.id,
		e.name,
		e.manager_id,
		s.level + 1
	FROM employees AS e
		JOIN subordinates AS s ON e.manager_id = s.id
)
SELECT id,
	name,
	LEVEL
FROM subordinates
ORDER BY LEVEL,
	id;
idnamelevel
1Anna Ivanova1
6Olga Novikova1
10Tatiana Lebedeva1
13Roman Fedorov1
17Alexey Belov1
20Sergey Kuznetsov1
24Larisa Titova1
28Polina Nikitina1
32Vadim Sorokin1
36Boris Panov1

Подробности

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

Рекурсивное выражение (WITH RECURSIVE) состоит из двух частей, соединённых через UNION ALL или UNION. Начальный запрос выполняется один раз и даёт первые строки. Рекурсивная часть ссылается на само выражение и выполняется снова и снова: на каждом шаге она видит только строки, добавленные на прошлом шаге. Работа заканчивается, когда шаг не добавил ни одной строки.

Ограничения на число шагов нет, поэтому в рекурсивной части нужно условие остановки, например WHERE n < 5. UNION отбрасывает повторяющиеся строки, и это тоже может остановить рекурсию, а UNION ALL оставляет все.

Смотрите также

Где изучить