Подзапросы: скалярный и в WHERE
Содержание курса
Некоррелированный подзапрос: логический порядок и выбор между подзапросом и JOIN
Оба подзапроса, которые мы разбирали, — некоррелированные: внутренний SELECT не содержит ни одной ссылки на столбцы внешнего запроса. Это ключевое свойство, которое определяет логику чтения.
Логически некоррелированный подзапрос вычисляется один раз и независимо: сначала отрабатывает внутренний запрос, получает результат, а затем внешний запрос использует этот результат как готовое значение или список. Именно так нужно читать и писать такие запросы — «что вычислится внутри» → «что с этим делает снаружи».
Физически оптимизатор СУБД может выбрать любой план: переставить порядок, превратить подзапрос в соединение, использовать индекс. Это его право, и правильность результата от этого не меняется — гарантию даёт именно логический контракт некоррелированного подзапроса.
Признак некоррелированности прост: откройте внутренний SELECT и проверьте, есть ли в нём имена таблиц или псевдонимы из внешнего FROM. Если нет — подзапрос некоррелированный.
Когда подзапрос, а когда JOIN. Это практический выбор, и критерий один: нужны ли вам столбцы из второй таблицы в результате?
Если нужно только отфильтровать строки основной таблицы по условию на другой — подзапрос в WHERE чище и точнее. Пример: «вывести имена клиентов, у которых есть хотя бы один заказ». Здесь из orders не нужно ничего выводить — только проверить факт существования строк.
SELECT name
FROM customers
WHERE customer_id IN (SELECT customer_id FROM orders);
Если сделать то же самое через JOIN, каждый клиент с тремя заказами появится в результате трижды — придётся добавлять DISTINCT или GROUP BY, что усложняет запрос без необходимости.
Если же нужно вывести, например, имя клиента и сумму его заказа рядом — без JOIN не обойтись, потому что orders.total_amount не попадёт в результат через подзапрос в WHERE.
Правило коротко: подзапрос — когда вторая таблица нужна только как источник условия; JOIN — когда нужны её данные в результирующих столбцах.
