0Pricing
SQL Academy · Урок

Общие табличные выражения (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 — локальная установка не требуется.

Все уроки этого курса

  1. Скалярные, строковые и табличные подзапросы
  2. Коррелированные и некоррелированные подзапросы
  3. Общие табличные выражения (WITH)
  4. Рекурсивные CTE для иерархий
← Назад к SQL Academy