Занятие 25. Подзапросы
⚡ Кратко: суть темы
Подзапрос — это SELECT внутри другого запроса. Используется в WHERE (фильтр) и FROM (временная таблица). Всегда в скобках.
- Скалярный — одно значение; с ним работают
=,>,<. - Многострочный — список значений; с ним работают
IN,ANY,ALL.
📖 Что такое подзапрос
Подзапрос (subquery) — это SQL-запрос, вложенный внутрь другого SQL-запроса. Внешний запрос использует результат подзапроса так же, как значение, таблицу или набор строк.
SELECT * FROM orders
WHERE customer_id IN (
SELECT id FROM customers WHERE city = 'Los Angeles'
);
- Внешний запрос:
SELECT * FROM orders ... - Подзапрос:
(SELECT id FROM customers WHERE city = 'Los Angeles')
Подзапрос всегда заключается в круглые скобки.
📖 Подзапрос в WHERE
Подзапрос в WHERE возвращает значение или набор значений, которые используются для фильтрации строк внешнего запроса.
SELECT * FROM orders
WHERE customer_id IN (
SELECT id FROM customers WHERE city = 'Los Angeles'
);
Сначала внутренний запрос находит идентификаторы клиентов из Лос-Анджелеса, затем внешний запрос выбирает их заказы.
📖 Подзапрос в FROM
Подзапрос в FROM создаёт временный набор данных, который используется как таблица. Обычно применяется для предварительной агрегации.
SELECT p.product_name, ps.total_orders, ps.total_revenue
FROM (
SELECT product_id,
COUNT(*) AS total_orders,
SUM(unit_price * quantity) AS total_revenue
FROM order_details
GROUP BY product_id
) AS ps
JOIN products AS p ON ps.product_id = p.id
ORDER BY ps.total_orders DESC
LIMIT 10;
Подзапрос агрегирует данные по продуктам; внешний запрос соединяет результат с products, чтобы получить названия.
📖 Скалярный подзапрос
Скалярный подзапрос возвращает ровно одно значение (одну строку и один столбец). Его можно использовать с операторами сравнения: =, <>, >, <, >=, <=.
SELECT *
FROM order_details
WHERE unit_price > (
SELECT AVG(unit_price) FROM order_details
);
Если скалярный подзапрос вернёт более одной строки, СУБД выдаст ошибку.
📖 Многострочный подзапрос
Многострочный подзапрос возвращает столбец с несколькими значениями. С ним используются операторы IN, ANY, ALL, EXISTS.
SELECT *
FROM orders
WHERE employee_id IN (
SELECT id FROM employees WHERE job_title = 'Sales Representative'
);
📖 Преимущества и недостатки
Преимущества
- Позволяют разбить сложную задачу на простые шаги.
- Часто читаемее сложных JOIN и UNION.
- Изолируют промежуточную логику.
Недостатки
- Могут работать медленнее эквивалентных JOIN.
- Глубоко вложенные подзапросы сложно отлаживать.
- Не всегда оптимизатор СУБД выбирает лучший план выполнения.