2.4. Вложенные подзапросы
Вложенный подзапрос – это запрос, включаемый в секцию where операторов select, delete, update или секцию having оператора select. Вложенные подзапросы включаются в секции оператора select с помощью операций сравнения, операции in и квантора exists. Вложенный подзапрос может содержать в своей секции where (having) вложенный подзапрос более низкого уровня.
Запросы с подзапросами могут обрабатываться, начиная от подзапросов самого нижнего уровня и заканчивая основным запросом. В этом случае вложенные подзапросы называются простыми. Возможен и обратный порядок: сначала выбирается одна строка по основному запросу, а затем, опираясь на результат его выполнения, начинает работать вложенный подзапрос. Это характерно для коррелированных вложенных подзапросов.
Чтобы лучше понять логику подзапросов обоих видов, рассмотрим конкретные примеры.
2.4.1. Простые вложенные подзапросы
Пусть требуется получить сведения о вагонах поезда «Смена». Данный запрос можно построить на основе соединения таблиц coaches и trains, в этом случае он будет выглядеть таким образом:
select coaches.coach_number, coaches.coach_type
from coaches, trains
where coaches.id_train = trains.id_train
and trains.train_name = ‘Смена’
Такие же результаты даст запрос, в котором используется простой вложенный подзапрос:
select coach_number, coach_type
from coaches
where id_train =
(select id_train from trains where train_name = ‘Смена’)
Поиск данных начинается с выполнения вложенного подзапроса select id_train from trains where train_name = ‘Смена’. По этому запросу выбирается идентификатор поезда с названием «Смена». Далее управление передается внешнему запросу, который выбирает в таблице coaches все строки, где значение в поле id_train совпадает с идентификатором, выбранным по вложенному подзапросу.
2.4.2. Коррелированные вложенные подзапросы
Пусть требуется найти поезд, в состав которого входит вагон с заданным идентификатором id_coach. Решение данной задачи с использованием вложенного подзапроса выглядит следующим образом:
select train_number, train_name
from trains
where 3 in
(select id_coach
from coaches
where id_train = trains.id_train)
Отличие этого запроса от предыдущих состоит в том, что вложенный подзапрос не может быть обработан прежде, чем отработает внешний запрос: вложенный подзапрос зависит от значения trains.id_train из внешнего запроса.
Порядок обработки данного коррелированного подзапроса следующий.
1. Сначала выбирается первая строка из таблицы trains по внешнему запросу. Предположим, что в этой строке id_train равен 1.
2. СУБД обрабатывает внутренний подзапрос, который, по сути дела, приобретает вид:
(select id_coach
from coaches
where id_train = 1)
Будут выбраны все вагоны, относящиеся к поезду с id_train = 1.
3. Далее СУБД должна проверить истинность условия во внешнем запросе: присутствует ли идентификатор 3 в числе идентификаторов, выбранных в п. 2?
Если условие выполнено, поиск прекращается, иначе шаги 1 – 3 повторяются: в пункте 1 выбирается следующая строка таблицы trains, с другим идентификатором id_train и т. п.
2.4.3. Коррелированные вложенные подзапросы, использующие квантор существования exists
Квантор существования в SQL представляется выражением exists(select …). Такое выражение считается истинным тогда и только тогда, когда результат выполнения запроса select представляется непустым множеством кортежей. Если запрос выдает пустое множество кортежей, то выражение exists(select …) ложно.
Результатом выполнения следующего запроса будут все поезда, в которых есть вагоны СВ.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.