Как сделать подзапрос в SQL (вложенный SELECT)?
Хочу выбрать сотрудников, у которых зарплата выше средней по компании. Среднее ведь сначала надо посчитать. Как сделать подзапрос — SELECT внутри другого SELECT? Где его можно писать?
2 ответа
Подзапрос — это запрос внутри запроса, в скобках. Его можно ставить в нескольких местах.
В WHERE (самый частый случай) — сотрудники с зарплатой выше средней:
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Внутренний запрос сначала посчитает одно число (среднее), и внешний сравнит с ним каждого.
Подзапрос может возвращать список значений — тогда используют IN:
SELECT name FROM customers
WHERE id IN (SELECT customer_id FROM orders WHERE total > 5000);
В FROM — подзапрос как «временная таблица»:
SELECT dept, avg_sal
FROM (
SELECT department AS dept, AVG(salary) AS avg_sal
FROM employees
GROUP BY department
) AS t
WHERE avg_sal > 50000;
Типы подзапросов по результату:
- скалярный — возвращает одно значение (как с AVG выше), годится для сравнения
=,>; - на список — много строк, используется с
IN,ANY,ALL; - коррелированный — ссылается на внешний запрос и выполняется для каждой его строки (мощно, но может быть медленно).
Частые ошибки:
- Скалярный подзапрос вернул больше одной строки — будет ошибка. Добавьте
LIMIT 1или агрегат. - Подзапросу в FROM обязательно нужен алиас (
AS t).
Если подзапрос становится громоздким или используется несколько раз, его удобнее вынести в CTE — общее табличное выражение через WITH:
WITH dept_avg AS (
SELECT department, AVG(salary) AS avg_sal
FROM employees GROUP BY department
)
SELECT e.name FROM employees e
JOIN dept_avg d ON e.department = d.department
WHERE e.salary > d.avg_sal;
Читается сверху вниз, как обычные шаги, и не плодит вложенность. По смыслу это тот же подзапрос, просто вынесенный «наверх» и названный.