Подзапросы во WHERE: IN и скалярное сравнение
Подзапросы SQL во WHERE: IN и скалярное сравнение — как использовать результат SELECT внутри другого SELECT.
Подзапрос (subquery) — это обычный
SELECT, вложенный в другой запрос в круглых скобках. Результат внутреннего запроса используется как условие или значение во внешнем.
Подзапрос в IN
Вместо того чтобы вручную перечислять нужные значения, можно получить их запросом:
Задача: найти всех сотрудников, которые работают в отделах, название которых начинается на «S» (Sales, ...).
-- Шаг 1: узнаём dept_id нужных отделов
SELECT dept_id FROM departments WHERE dept_name LIKE 'S%';
Результат:
dept_id ------- 5
-- Шаг 2: находим сотрудников этих отделов через подзапрос
SELECT emp_name, dept_id
FROM employees
WHERE dept_id IN (
SELECT dept_id FROM departments WHERE dept_name LIKE 'S%'
);
Результат:
emp_name | dept_id -------------+-------- Sarah Connor | 5
Скалярный подзапрос — сравнение с одним значением
Если подзапрос возвращает одну строку и один столбец, его можно сравнивать с помощью =, >, <:
-- Сотрудники с зарплатой выше средней
SELECT emp_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
ORDER BY salary DESC;
Результат:
emp_name | salary -------------+------- Sarah Connor | 8000 Rick Deckard | 7200 Tony Montana | 6500
Средняя зарплата — 6460. Все трое зарабатывают больше.
NOT IN с подзапросом
Найдём сотрудников, которые не относятся ни к одному из «больших» отделов (Sales или Finance):
SELECT emp_name, dept_id
FROM employees
WHERE dept_id NOT IN (
SELECT dept_id FROM departments
WHERE dept_name IN ('Sales', 'Finance')
)
AND dept_id IS NOT NULL;
Результат:
emp_name | dept_id ------------+-------- Tony Montana | 1 Ethan Hunt | 4
Важно: если подзапрос для
NOT INможет вернуть NULL, вся проверка даёт неожиданный результат. ДобавляйтеWHERE col IS NOT NULLвнутри подзапроса или используйтеNOT EXISTS.
Несколько уровней вложенности
-- Сотрудник с максимальной зарплатой в отделе 'Finance'
SELECT emp_name, salary
FROM employees
WHERE salary = (
SELECT MAX(salary)
FROM employees
WHERE dept_id = (
SELECT dept_id FROM departments WHERE dept_name = 'Finance'
)
);
Результат:
emp_name | salary -------------+------- Rick Deckard | 7200
Коротко
- Подзапрос — SELECT в скобках, вложенный в другой запрос.
IN (SELECT ...)— проверяет вхождение в набор результатов.- Скалярный подзапрос возвращает одно значение и используется в
=,>,<. - При
NOT INубедитесь, что подзапрос не возвращает NULL.