Ответ
Подзапрос — это запрос, вложенный в другой SQL-запрос. Он может использоваться в различных частях основного запроса.
Пример 1: Подзапрос в условии WHERE (с IN) Найти всех сотрудников, которые работают в отделах, расположенных в Лондоне.
SELECT employee_id, first_name, last_name
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = 'LON' -- Предположим, 'LON' это код Лондона
);
Пример 2: Коррелированный подзапрос в SELECT Для каждого сотрудника вывести его зарплату и среднюю зарплату по его отделу.
SELECT
employee_id,
first_name,
salary,
(
SELECT AVG(salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
) AS avg_department_salary
FROM employees e1;
Пример 3: Подзапрос как производная таблица (в FROM) Найти отделы со средней зарплатой выше средней по компании.
SELECT department_id, avg_sal
FROM (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
) AS dept_avg
WHERE avg_sal > (
SELECT AVG(salary) FROM employees
);
Ключевой момент: Подзапросы в WHERE и SELECT должны возвращать один столбец (или одно скалярное значение). Подзапрос в FROM должен иметь псевдоним (AS dept_avg).
Ответ 18+ 🔞
А, ну вот, подзапросы, ёпта! Это когда ты в одном запросе засовываешь другой запрос, как матрёшку. Типа «запрос в запросе», чтобы не делать два отдельных. Хитро, да? Сейчас разжуём.
Пример 1: Подзапрос в условии WHERE (с IN)
Смотри, задача: найти всех работяг, которые трудятся в отделах, сидящих в Лондоне. Делаем так: сначала внутренним запросом выясняем, какие отделы (их department_id) вообще в Лондоне валяются. А потом внешним запросом выбираем всех, кто в этих отделах числится. Всё просто, как три копейки.
SELECT employee_id, first_name, last_name
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = 'LON' -- Допустим, 'LON' это и есть Лондон, ядрёна вошь
);
Пример 2: Коррелированный подзапрос в SELECT (самый интересный)
Тут уже веселее. Хотим для каждого чувака не только его зарплату, но и среднюю по его же отделу, чтобы было с чем сравнить. Вот и лепим подзапрос прямо в список выборки. Он «коррелированный», потому что ссылается на поле (e1.department_id) из внешнего запроса. Для каждой строчки e1 этот подзапрос выполняется заново, считая среднюю только по его отделу. Компьютер, конечно, охуевает от нагрузки, но что поделать.
SELECT
employee_id,
first_name,
salary,
(
SELECT AVG(salary)
FROM employees e2
WHERE e2.department_id = e1.department_id -- Вот эта связка — ключ!
) AS avg_department_salary
FROM employees e1;
Пример 3: Подзапрос как производная таблица (в FROM)
А это уже высший пилотаж. Сначала внутренним запросом создаём виртуальную табличку: отдел и средняя зарплата в нём. А потом уже из этой таблички внешним запросом отбираем только те отделы, где средняя зарплата выше средней по всей конторе. Главное — не забыть дать этой виртуальной таблице псевдоним (AS dept_avg), а то СУБД начнёт материться, что не понимает, откуда данные брать.
SELECT department_id, avg_sal
FROM (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
) AS dept_avg -- Без этого псевдонима — никуда, доверия ебать ноль!
WHERE avg_sal > (
SELECT AVG(salary) FROM employees
);
Ключевой момент, который надо запомнить, чтобы не облажаться:
- Если лепишь подзапрос в
WHEREили вSELECT(как в примерах 1 и 2), он должен возвращать один столбец. А лучше вообще одно значение, скаляр. Иначе будет тебе, чувак, ошибка — овердохуища данных, а системе надо одну цифру или один список ID. - Если используешь подзапрос в
FROM(как в примере 3) — это уже целая таблица. Но её обязательно надо назвать (дать псевдоним черезAS). Без этого — сразу в пизду, SQL не примет.