← Все вопросы

Как сделать подзапрос в SQL (вложенный SELECT)?

Задан 1 месяц назад1.2к просмотров2 ответа
10

Хочу выбрать сотрудников, у которых зарплата выше средней по компании. Среднее ведь сначала надо посчитать. Как сделать подзапрос — SELECT внутри другого SELECT? Где его можно писать?

2 ответа

15
✓ Принятый ответ — помог автору

Подзапрос — это запрос внутри запроса, в скобках. Его можно ставить в нескольких местах.

В 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;
  • коррелированный — ссылается на внешний запрос и выполняется для каждой его строки (мощно, но может быть медленно).

Частые ошибки:

  1. Скалярный подзапрос вернул больше одной строки — будет ошибка. Добавьте LIMIT 1 или агрегат.
  2. Подзапросу в FROM обязательно нужен алиас (AS t).
6

Если подзапрос становится громоздким или используется несколько раз, его удобнее вынести в 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;

Читается сверху вниз, как обычные шаги, и не плодит вложенность. По смыслу это тот же подзапрос, просто вынесенный «наверх» и названный.

Ваш ответ

Войдите, чтобы ответить на вопрос.