Скалярные подзапросы в SELECT и WHERE
Однозначные подзапросы и ошибка, возникающая при возврате более одной строки.
«Скалярные подзапросы в SELECT и WHERE» — бесплатный урок SQL Interview Prep на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Interview Prep содержит 4 уроков всего.
Что интервьюер подразумевает под скалярным подзапросом
Скалярный подзапрос — это запрос, который возвращает ровно одну строку и один столбец — единственное значение. Поскольку он вычисляется в одно значение, SQL позволяет использовать его почти везде, где допустима литеральная константа: в SELECT, WHERE, HAVING и даже ORDER BY.
- Интервьюеры проверяют, знаете ли вы правило «одна строка, один столбец».
- Типичная ловушка: подзапрос, который случайно возвращает больше одной строки.
Если Вы чётко сформулируете это определение, первый этап проверки уже пройден.
Скалярный подзапрос в списке SELECT
Размещение скалярного подзапроса в списке SELECT позволяет добавить вычисляемое единичное значение к каждой результирующей строке. Здесь мы показываем каждого сотрудника рядом со средней зарплатой по всей компании.
Подзапрос (SELECT AVG(salary) FROM employees) выполняется и сводит всю таблицу к одному числу, после чего это число повторяется в каждой строке.
SELECT
name,
salary,
(SELECT AVG(salary) FROM employees) AS company_avg
FROM employees;Скалярный подзапрос в WHERE
То же единичное значение может использоваться для фильтрации. На собеседованиях очень часто просят найти всех, кто получает больше средней зарплаты в компании.
Подзапрос один раз вычисляет среднее значение, после чего с ним сравнивается каждая строка внешнего запроса. Это NOT коррелированный подзапрос — внутренний запрос не зависит от внешней строки, поэтому выполняется один раз.
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);Ошибка «более одной строки»
Именно эту ошибку интервьюеры ожидают от Вас. Если подзапрос используется с = или >, но возвращает несколько строк, СУБД выдаёт сообщение:
- PostgreSQL: подзапрос, использованный как выражение, вернул более одной строки
- MySQL: подзапрос возвращает более одной строки
Приведённый ниже запрос завершается ошибкой, потому что в отделе 5 может быть несколько сотрудников — этот подзапрос не является скалярным.
SELECT name
FROM employees
WHERE salary = (SELECT salary FROM employees WHERE dept_id = 5);Как гарантировать, что подзапрос будет скалярным
Два надёжных способа гарантировать одно значение:
- Используйте агрегатную функцию, например
MAX,MINилиAVG: агрегатные функции безGROUP BYвсегда возвращают одну строку. - Используйте
LIMIT 1(PostgreSQL/MySQL) илиFETCH FIRST 1 ROW ONLYпослеORDER BY.
Исправленный вариант ниже запрашивает самую высокую зарплату в отделе 5.
SELECT name
FROM employees
WHERE salary = (
SELECT MAX(salary) FROM employees WHERE dept_id = 5
);Скалярные подзапросы возвращают NULL, если строк нет
Тонкий момент для собеседования: если скалярный подзапрос находит ноль строк, ошибки не возникает — он возвращает NULL. Затем это NULL распространяется в сравнении.
Поскольку salary > NULL вычисляется как UNKNOWN (а не как истина), внешний запрос не возвращает строк. Кандидаты часто ожидают здесь ошибку; правильный ответ — пустой результат без сообщения.
SELECT name, salary
FROM employees
WHERE salary > (
SELECT AVG(salary) FROM employees WHERE dept_id = 9999
);Пример: сотрудники с зарплатой выше средней и разница
Объединим оба варианта использования. Мы покажем каждого сотрудника с зарплатой выше средней и то, насколько его зарплата превышает среднюю. Один и тот же скалярный подзапрос появляется в SELECT и WHERE.
Интервьюер может спросить, выполняется ли подзапрос дважды. Логически он встречается два раза, но хороший оптимизатор может вычислить некоррелированный подзапрос один раз и повторно использовать его.
SELECT
name,
salary,
salary - (SELECT AVG(salary) FROM employees) AS above_avg
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
ORDER BY above_avg DESC;Скалярный подзапрос в ORDER BY
Поскольку скалярный подзапрос является обычным значением, его также разрешено использовать в ORDER BY. Это редко бывает самым ясным решением, но интервьюеры любят проверять, знаете ли Вы о такой возможности.
Здесь мы сортируем отделы по значению, полученному из другой таблицы, — численности сотрудников каждого отдела — без соединения таблиц.
SELECT d.dept_name
FROM departments d
ORDER BY (
SELECT COUNT(*) FROM employees e WHERE e.dept_id = d.id
) DESC;Скалярный и коррелированный: где проходит граница
Пример с ORDER BY выше скрыто ссылается на d.id из внешнего запроса — поэтому это коррелированный скалярный подзапрос, выполняющийся один раз для каждой строки внешнего запроса.
Интервьюеры любят проверять это различие:
- Некоррелированный скалярный подзапрос: самодостаточен, выполняется один раз.
- Коррелированный скалярный подзапрос: ссылается на внешнюю строку, выполняется для каждой строки.
Оба подзапроса остаются скалярными и возвращают одно значение, но их производительность может сильно различаться.
Когда не следует использовать скалярный подзапрос
Коррелированный скалярный подзапрос в списке SELECT удобен, но на больших таблицах может работать медленно — он выполняется для каждой строки. Интервьюеры ожидают, что Вы знаете альтернативы:
LEFT JOINс предварительно агрегированной производной таблицей.- Оконная функция, например
AVG(salary) OVER ().
Вариант с оконной функцией ниже формирует тот же столбец со средней зарплатой по компании без отдельного прохода по подзапросу.
SELECT
name,
salary,
AVG(salary) OVER () AS company_avg
FROM employees;Короткая формулировка для собеседования
Если Вас попросят определить скалярный подзапрос, скажите: «Скалярный подзапрос возвращает одну строку и один столбец, поэтому ведёт себя как единственное значение и может использоваться везде, где разрешена литеральная константа. Если он возвращает больше одной строки, СУБД выдаёт ошибку; если не возвращает строк, он даёт NULL».
Одно это предложение охватывает определение, случай ошибки и особый случай с NULL — три момента, на которые обращает внимание каждый интервьюер.
Быстрая проверка
Проверьте, как работают скалярные подзапросы.
Итоги
Теперь Вы уверенно работаете со скалярными подзапросами:
- Определение: одна строка и один столбец — подзапрос можно использовать как литеральную константу в SELECT, WHERE, HAVING и ORDER BY.
- Несколько строк с операторами =/> приводят к ошибке; обеспечить скалярный результат можно с помощью агрегатной функции или
LIMIT 1. - Ноль строк даёт NULL, из-за чего строки без сообщения исключаются при фильтрации.
- Коррелированные скалярные подзапросы выполняются для каждой строки; если важна производительность, предпочитайте соединения или оконные функции.
Далее: подзапросы в предложении FROM, результатом которых является целая виртуальная таблица.
Часто задаваемые вопросы
Урок «Скалярные подзапросы в SELECT и WHERE» бесплатный?
Да — полный текст урока «Скалярные подзапросы в SELECT и WHERE» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Interview Prep, подпишись на CoddyKit PRO. Курс SQL Interview Prep содержит 4 уроков всего.
Чему я научусь в уроке «Скалярные подзапросы в SELECT и WHERE»?
Однозначные подзапросы и ошибка, возникающая при возврате более одной строки. Ты практикуешь SQL Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Interview Prep?
Предыдущий опыт не требуется. SQL Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Скалярные подзапросы в SELECT и WHERE»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Interview Prep?
Да. Каждый урок SQL Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Скалярные подзапросы в SELECT и WHERE
- Подзапросы в разделе FROM (производные таблицы)
- Подзапросы IN, ANY и ALL
- Производительность EXISTS и IN