Общие табличные выражения (WITH)
Преобразуйте вложенные запросы в понятные предложения WITH, объединяйте CTE в цепочки и изучайте правила материализации в PostgreSQL 12+
«Общие табличные выражения (WITH)» — бесплатный урок SQL Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.
Что такое CTE?
Общее табличное выражение (CTE) — это именованный подзапрос, определённый с помощью WITH:
WITH paid_orders AS (
SELECT * FROM orders WHERE status = 'paid'
)
SELECT user_id, COUNT(*)
FROM paid_orders
GROUP BY user_id;Зачем использовать CTE?
Три главных преимущества:
- Читаемость — разбивайте запрос из 200 строк на именованные шаги
- Повторное использование — обращайтесь к одному промежуточному результату несколько раз
- Рекурсия — только CTE поддерживают рекурсивные запросы (в следующем уроке)
Объединение CTE в цепочку
Определите несколько CTE в одном WITH и используйте один из них в следующем:
WITH last_30 AS (
SELECT * FROM orders WHERE created_at >= NOW() - INTERVAL '30 days'
),
per_user AS (
SELECT user_id, SUM(total) AS revenue FROM last_30 GROUP BY user_id
)
SELECT u.email, p.revenue
FROM users u
JOIN per_user p ON p.user_id = u.id
ORDER BY p.revenue DESC LIMIT 20;Повторное использование CTE
Если один и тот же промежуточный результат используется дважды, CTE ясно показывает намерение:
WITH recent_users AS (
SELECT id FROM users WHERE created_at >= NOW() - INTERVAL '7 days'
)
SELECT 'new orders' AS metric, COUNT(*) FROM orders
WHERE user_id IN (SELECT id FROM recent_users)
UNION ALL
SELECT 'new revenue', SUM(total) FROM orders
WHERE user_id IN (SELECT id FROM recent_users);Материализация CTE (PostgreSQL ≤ 11)
Старые версии PG всегда материализовали результат CTE, создавая барьер для планировщика. Начиная с PG 12 планировщик по умолчанию встраивает CTE, если явно не указать иное:
-- Force the old materialise behaviour (rarely needed):
WITH x AS MATERIALIZED (SELECT ...) ...
-- Force inlining (default):
WITH x AS NOT MATERIALIZED (SELECT ...) ...CTE, изменяющие данные
В CTE можно использовать INSERT/UPDATE/DELETE — это удобно для атомарного перемещения строк между таблицами:
WITH moved AS (
DELETE FROM orders WHERE status = 'archived' RETURNING *
)
INSERT INTO orders_archive SELECT * FROM moved;CTE в DML
RETURNING + WITH для сценария «найти и выполнить действие»:
WITH cancelled AS (
UPDATE orders SET status = 'cancelled'
WHERE created_at < NOW() - INTERVAL '14 days'
AND status = 'pending'
RETURNING id
)
INSERT INTO audit_log (event, order_id)
SELECT 'auto-cancel', id FROM cancelled;Порядок выполнения
CTE, изменяющие данные, выполняются независимо в одном снимке данных. Каждый оператор видит состояние ДО начала всех изменений — это неожиданно, но предсказуемо.
CTE, подзапросы и представления
Сравнение:
- Подзапрос — определяется непосредственно в запросе; используется один раз
- CTE — имеет имя; используется несколько раз в пределах запроса; исчезает после завершения запроса
- Представление — имеет имя; сохраняется; может использоваться в разных запросах
Не злоупотребляйте CTE
Если оборачивать всё в CTE, запросы становятся понятнее, но стоимость операций может быть скрыта. При больших промежуточных результатах планировщик может выбрать менее эффективные планы, чем для эквивалентного JOIN.
Итоги
CTE дают имена промежуточным запросам.
- Повышают читаемость
- Позволяют повторно использовать результат в одном запросе
- Необходимы для рекурсии
- По умолчанию встраиваются в современных версиях PG
Быстрая проверка
Какое ключевое слово начинает общее табличное выражение?
Часто задаваемые вопросы
Урок «Общие табличные выражения (WITH)» бесплатный?
Да — полный текст урока «Общие табличные выражения (WITH)» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.
Чему я научусь в уроке «Общие табличные выражения (WITH)»?
Преобразуйте вложенные запросы в понятные предложения WITH, объединяйте CTE в цепочки и изучайте правила материализации в PostgreSQL 12+ Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Academy?
Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Общие табличные выражения (WITH)»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Academy?
Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Скалярные, строковые и табличные подзапросы
- Коррелированные и некоррелированные подзапросы
- Общие табличные выражения (WITH)
- Рекурсивные CTE для иерархий