Перейти к содержимому
Учи.Онлайн Выбрать школу
Статья

Подзапросы в SQL: как разбирать вложенные запросы на практике

Подзапрос позволяет использовать результат одного SQL-запроса внутри другого. Внутренний запрос может вернуть одно значение, набор строк или ответ на вопрос о существовании связанных данных. От формы результата зависит, каким образом он участвует в общей команде. Обучение подзапросам становится понятнее, когда каждая вложенная часть рассматривается как самостоятельная задача. Сначала ясно, какие данные она получает, затем — как внешний запрос использует этот результат. Такой порядок помогает читать SQL по смыслу и замечать ошибки, которые скрываются за большим количеством скобок.

Автор: редакция Учи.ОнлайнОтветственный редактор: Дмитрий Игнатьев
Содержание
Небольшие вложенные бумажные карточки на столе рядом с экраном редактора запросов

Как одно значение становится условием отбора

Пусть таблица orders хранит суммы заказов. Для получения заказов выше среднего можно сначала вычислить среднее значение, а затем использовать его в условии:

SELECT id, amount
FROM orders
WHERE amount > (
  SELECT AVG(amount)
  FROM orders
);

Внутренняя часть возвращает одно агрегированное значение. Если суммы равны 100, 200 и 300, среднее составляет 200, поэтому условию соответствует заказ с суммой 300. На таком наборе связь между двумя частями запроса видна без дополнительных предположений.

Важна именно форма результата. Там, где выражению требуется одно значение, несколько возвращённых строк могут привести к ошибке. Поэтому при чтении подзапроса рассматривают не только названия полей, но и то, сколько строк и столбцов он способен вернуть в данной ситуации.

Когда нужен набор строк

В другой задаче внутренний запрос может вернуть несколько идентификаторов. Внешняя часть использует их как набор для отбора. Например, можно получить заказы клиентов из определённой группы, если внутренний запрос возвращает идентификаторы именно этой группы.

Такой результат отличается от одного числа в предыдущем примере. Оператор и дальнейшее использование должны соответствовать форме данных. Это помогает понять, почему простая замена знака сравнения не всегда сохраняет смысл команды: меняется не только запись, но и тип ожидаемого результата.

Вложенный запрос может находиться и во FROM, где его результат рассматривается как табличный источник. Тогда важно понимать названия и смысл полученных столбцов. Внешний запрос продолжает работу с этим промежуточным набором так же осмысленно, как с другими источниками данных.

Как EXISTS выражает наличие связанных данных

Иногда нужен ответ на вопрос, существует ли хотя бы одна подходящая строка. Например, требуется список клиентов, у которых есть заказы. Такое условие можно выразить через EXISTS:

SELECT c.id
FROM customers AS c
WHERE EXISTS (
  SELECT 1
  FROM orders AS o
  WHERE o.customer_id = c.id
);

Внутренняя часть связана с текущей строкой внешней через идентификатор клиента. Для EXISTS существенен сам факт наличия результата. Один клиент остаётся одной строкой внешнего запроса, даже если подходящих заказов у него несколько.

В документации PostgreSQL о подзапросах этот оператор рассматривается вместе с другими формами проверки. В учебной работе его удобно связывать с обычным вопросом: есть ли связанные записи, удовлетворяющие заданному условию.

Как учатся применять подзапросы в аналитике

Курс «SQL для работы с данными и аналитики» в Яндекс Практикуме включает подзапросы во FROM и WHERE, общие табличные выражения и объединение вложенных частей. Эти темы связываются с получением данных для анализа. Слушатель учится выражать последовательность расчёта через несколько понятных SQL-шагов.

Открыть курс SQL для аналитики

В проекте используется база с венчурными инвесторами, стартапами и инвестициями; далее подзапросы встречаются при расчёте показателей. Такой формат помогает видеть назначение приёма: внутренняя часть подготавливает данные, которые нужны для ответа на определённый аналитический вопрос.

Как развивают работу со сложными запросами

Курс «SQL для разработки» в Яндекс Практикуме рассматривает подзапросы и общие табличные выражения в разделе продвинутой работы с данными. Рядом изучаются представления, типы данных и транзакции. Это помогает связать вложенную команду с устройством базы приложения и дальнейшим использованием результата.

Открыть SQL для разработки

Проектные задачи включают прикладные схемы и запросы разной сложности. Для разработчика ценность такой подготовки — в понимании, как промежуточный набор участвует в общей работе с данными. Дальнейшая оптимизация позволяет рассматривать и смысл запроса, и способ его выполнения.

Что меняет связь с внешней строкой

Коррелированный подзапрос использует значение из окружающего запроса. В примере с клиентами это c.id, с которым сопоставляется идентификатор заказчика. Такая связь объясняет, почему условие рассматривается относительно конкретной внешней записи.

Это описание смысла не следует превращать в универсальное утверждение о физическом выполнении. СУБД может выбирать разные способы реализации запроса и преобразовывать его при построении плана. Для обучения полезно сначала понимать требуемый результат, а затем отдельно рассматривать фактический план работы.

Такая последовательность помогает сравнивать подзапрос и соединение таблиц. JOIN может быть нужен для получения полей связанных строк, а EXISTS — для отбора по факту их наличия. При нескольких совпадениях количество строк результата зависит от выбранной формы, поэтому различие имеет практическое значение.

Почему NULL влияет на отрицательные условия

NULL связан с отсутствующим или неизвестным значением и участвует в логике SQL особым образом. Условие может получить неизвестный результат, а WHERE оставляет строки, для которых условие истинно. Это важно при использовании NOT IN, если во внутреннем наборе встречается NULL.

Поэтому формулировки «идентификатора нет среди значений» и «не существует подходящей связанной записи» требуют внимательного чтения. Их результат зависит от данных и условий сравнения. В некоторых задачах проверка через NOT EXISTS позволяет выразить именно отсутствие связанных строк с заданным признаком.

На учебном наборе полезно видеть эти случаи отдельно. Несколько заполненных идентификаторов дают одну картину, добавление NULL может изменить результат отрицательной проверки. Тогда специальное правило становится понятным через данные, а не остаётся неожиданным исключением в длинном запросе.

Форма подзапроса Как используется результат
Одно значение Участвует в выражении или сравнении
Набор строк Даёт значения для дальнейшего отбора
Табличный источник во FROM Подготавливает промежуточную таблицу
EXISTS Проверяет наличие подходящих строк
Коррелированная часть Использует значение из внешней записи

Как группировка меняет смысл строки

Внутренний запрос может сначала собрать сумму заказов по клиенту, а внешний — оставить клиентов с нужным итогом:

SELECT customer_id, total
FROM (
  SELECT customer_id, SUM(amount) AS total
  FROM orders
  GROUP BY customer_id
) AS totals
WHERE total > 1000;

До группировки строка описывала отдельный заказ. В промежуточном результате она относится уже к клиенту и общей сумме его заказов. Внешний запрос работает именно с этим новым уровнем подробности, поэтому условие по total имеет понятный предмет.

Имя totals обозначает подготовленный набор во внешней части. По такой структуре удобно читать расчёт: сначала получить итоги для клиентов, затем отобрать нужные результаты. Различение уровней помогает замечать, где в сложной команде теряется исходный смысл данных.

Как пошаговый разбор помогает читать большой запрос

Большая команда становится понятнее, если каждой части дать словесное назначение. Одна получает выбранных клиентов, другая считает суммы, третья оставляет нужные результаты. Эти формулировки помогают удерживать связь между SQL и исходным вопросом, который решается с помощью данных.

Затем рассматривается форма промежуточного результата. Важны количество строк, уровень подробности и возможное появление NULL. Если эти свойства понятны, легче заметить случайное размножение записей или ситуацию, где в сравнении ожидалось одно значение, а получился набор.

Так подзапросы становятся инструментом ясного рассуждения. Слушатель может объяснить, что подготовила внутренняя часть и почему внешний запрос использует именно такой результат. На этой основе проще развивать аналитические и разработческие навыки SQL, сохраняя понятный смысл даже у достаточно сложной команды.