Подзапросы во 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.
Проверьте себя
1. Как называется подзапрос, который возвращает ровно одно значение?
AМногострочный подзапрос
BСкалярный подзапрос
CКоррелированный подзапрос
DВстроенное представление
2. Что произойдёт с NOT IN, если подзапрос вернёт NULL среди значений?
ANULL игнорируется, остальные значения проверяются нормально
BВся проверка NOT IN вернёт NULL (нет строк в результате)
CПроизойдёт ошибка
DNULL трактуется как 0
3. В каком месте запроса может стоять подзапрос?
AТолько во WHERE
BТолько в SELECT
CВо WHERE, FROM, SELECT и HAVING
DТолько в JOIN
Поддержать проект