Оператор выборки в Transact-SQL. Использование представлений (Лабораторная работа № 3), страница 8

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 …) ложно.

Результатом выполнения следующего запроса будут все поезда, в которых есть вагоны СВ.