0Pricing
SQL Interview Prep · Урок

Скалярные подзапросы в 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 — локальная установка не требуется.

Все уроки этого курса

  1. Скалярные подзапросы в SELECT и WHERE
  2. Подзапросы в разделе FROM (производные таблицы)
  3. Подзапросы IN, ANY и ALL
  4. Производительность EXISTS и IN
← Назад к SQL Interview Prep