SQL. Оператор WITH — зачем он нам?
Хочу сегодня поговорить с вами про такой инструмент в написании SQL-запросов, как WITH.
💡 Что это такое?
В общем и целом — это синтаксический сахар, который помогает понятным и читаемым образом получить необходимые данные из БД. Но всё по порядку.
Простой пример:
Допустим, у нас есть таблица sales:
id employee_id amount
1 101 200
2 102 150
3 101 100
Задача: Сколько продаж сделал каждый сотрудник, если его сумма продаж выше 200?
Вот как это можно сделать с помощью WITH:
WITH sales_summary AS (
SELECT employee_id, SUM(amount) AS total_sales
FROM sales
GROUP BY employee_id
)
SELECT employee_id, total_sales
FROM sales_summary
WHERE total_sales > 200;
Что произошло?
Создана временная таблица sales_summary при помощи WITH, которую дальше можно использовать как обычную.
А можно было проще? Да!
Для этой задачи, честно говоря, можно было бы обойтись без WITH, и использовать HAVING:
SELECT employee_id, SUM(amount) AS total_sales
FROM sales
GROUP BY employee_id
HAVING SUM(amount) > 200;
🔎 Но цель была — показать, как работает WITH, а не сделать самый короткий запрос.
Когда WITH реально раскрывается:
Представим чуть более сложную задачу:
Найти продажи по сотрудникам, затем взять топ-3 по сумме.
WITH sales_summary AS (
SELECT employee_id, SUM(amount) AS total_sales
FROM sales
GROUP BY employee_id
)
SELECT *
FROM sales_summary
ORDER BY total_sales DESC
LIMIT 3;
🎯 Здесь HAVING уже не поможет — он не умеет работать с ORDER BY и LIMIT после агрегации.
А с WITH — всё наглядно и читаемо.
А насколько WITH затратный для базы?
Хороший вопрос.
На практике, в PostgreSQL WITH раньше (до версии 12) всегда материализовался — сначала считался полностью, а потом уже использовался. Сейчас ситуация лучше — запрос может быть встроен обратно (inlined), если это безопасно.
💬 Так что да, иногда может быть небольшое ухудшение производительности. Но чаще — это не критично, особенно если ты выигрываешь в читаемости и логике.
Когда WITH реально полезен:
1. Когда агрегат нужно переиспользовать в другом контексте (например, джойнить с другой таблицей)
2. Когда нужно сгруппировать данные, а потом делать с ними дополнительные действия
3. Когда запрос сложный, и хочется разбить его на понятные части
4. Когда есть несколько уровней агрегации
Всем добра!
#sql #sql_with
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ