intermediate

CTE

Используйте CTE для readability, recursive queries и staging complex operations, проверяя plan behavior.

CTE (`WITH`) улучшают читаемость и дают рекурсию. В PostgreSQL 12+ нерекурсивные CTE часто инлайнятся; в старых версиях по умолчанию материализовались — это могло помочь или навредить плану.

					-- Читаемая стадия
WITH recent AS (
  SELECT * FROM orders
  WHERE created_at >= now() - interval '30 days'
),
totals AS (
  SELECT customer_id, sum(amount) AS total
  FROM recent
  GROUP BY customer_id
)
SELECT c.name, t.total
FROM totals t
JOIN customers c ON c.id = t.customer_id
ORDER BY t.total DESC
LIMIT 20;

-- Рекурсивная иерархия
WITH RECURSIVE tree AS (
  SELECT id, parent_id, name, 1 AS depth
  FROM categories WHERE parent_id IS NULL
  UNION ALL
  SELECT c.id, c.parent_id, c.name, t.depth + 1
  FROM categories c
  JOIN tree t ON c.parent_id = t.id
)
SELECT * FROM tree;
				

Всегда смотрите `EXPLAIN`: CTE с ранним фильтром может хорошо инлайниться; скан огромной таблицы останется дорогим и при материализации.

На интервью: читаемость CTE vs подзапросы; рекурсивные CTE (оргструктуры, графы); тезис «CTE всегда медленные» устарел для современного PostgreSQL.

Типовые ошибки: предполагать материализацию без плана; рекурсия без защиты от циклов; дублирование тяжёлых сканов в ветках CTE.

Компромисс — ясность SQL против контроля планировщика; CTE структурируют сложный запрос, но план нужно проверять на реальных объёмах.

Чеклист:

  • Именуйте промежуточные шаги через CTE.
  • Защищайте рекурсию от циклов и бесконечной глубины.
  • Сравните EXPLAIN с переписыванием без CTE.
  • Одна хорошо отфильтрованная база лучше повторяющихся подзапросов.