CTE с WITH
Содержание курса
В прошлом уроке скалярный подзапрос жил внутри WHERE прямо на месте. Логически он вычислялся первым, возвращал одно значение, а внешний запрос использовал его в условии; физический порядок при этом выбирал оптимизатор. Этот механизм работает, но при усложнении запроса вложенные конструкции становятся трудночитаемыми. CTE позволяет дать промежуточному результату имя и вынести его наверх, не меняя логику.
Синтаксис WITH cte_name AS (...) и природа CTE как именованного временного результата
CTE объявляется перед основным запросом: ключевое слово WITH, затем имя, затем AS и в скобках — обычный SELECT. После закрывающей скобки сразу идёт основной запрос, который обращается к этому имени как к обычной таблице.
WITH expensive_products AS (
SELECT product_id, title, price
FROM products
WHERE price > 1000
)
SELECT title, price
FROM expensive_products
ORDER BY price DESC;
Здесь expensive_products — это не таблица в базе данных. Это имя, которое живёт ровно на время выполнения одного SQL-выражения. Точка с запятой стоит только в конце основного SELECT — весь блок от WITH до последней строки является единым запросом.
Что именно происходит внутри: СУБД читает определение CTE, а затем основной SELECT может использовать его как табличный источник в FROM или JOIN; после этого столбцы CTE доступны в SELECT, WHERE и других предложениях. К CTE также можно обратиться из подзапроса внутри WHERE. Оптимизатор сам решает, вычислять ли CTE заранее или встраивать его как подзапрос — это детали реализации, не влияющие на результат.
Важная граница: CTE не создаёт никакого объекта в схеме базы. Если написать следующий SQL-запрос (уже после точки с запятой), имя expensive_products там будет недоступно — СУБД вернёт ошибку «no such table». Это принципиально отличает CTE от представления (VIEW), которое сохраняется в схеме, и от временной таблицы. CTE — это именованный промежуточный результат только для текущего запроса.
Именно это свойство делает CTE удобным инструментом для разбивки сложного запроса на читаемые шаги: каждый шаг получает имя, отражающее смысл, а не синтаксическую позицию.
