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.
- Одна хорошо отфильтрованная база лучше повторяющихся подзапросов.