Подзапросы перед которыми стоит ключевое слово IN
Подзапросы, перед которыми стоит ключевое слово IN
Один из видов вложенных запросов работает по следующему принципу: одиночное значение сравнивается с набором значений, возвращаемым SELECT. В этом случае используется предикат IN (в):
SELECT слисок_столбцов
FROM таблица
WHERE выражение IN (подзапрос) ;
Проверяется значение выражения, которое находится в предложении WHERE. Если это значение есть в списке, возвращенном подзапросом, то предложение WHERE возвращает логическое значение True, а перечисленные табличные столбцы обрабатываются и добавляются в выводимую таблицу. В подзапросе можно указать или ту же таблицу, что и во внешнем запросе, или же какую-нибудь другую.
Чтобы показать, как работает подобный запрос, я воспользуюсь базой данных компании Zetec. Предположим, что в компьютерной отрасли образовался дефицит мониторов. Под вопросом оказывается выпуск готовых товаров, в состав которых должны входить мониторы. Вы хотите знать, что это за товары. Введите следующий запрос:
SELECT Model
FROM COMP_USED
WHERE CompID IN
(SELECT CompID
; FROM COMPONENT
WHERE CompType = 'Monitor') ;
Вначале SQL выполняет запрос самого нижнего уровня, т.е. обрабатывает таблицу COMPONENT, возвращая значения CompID из тех строк, в которых значением СотрТуре является 'Monitor'. В результате появляется список идентификационных номеров всех мониторов. Затем внешний запрос сравнивает с полученным списком значение CompID из каждой строки таблицы COMP_USED. Если сравнение бьло успешным, то значение Model из той же строки добавляется в виртуальную таблицу, создаваемую внешним оператором SELECT. В результате появляется список всех моделей ваших товаров, в состав которых входит монитор. Следующий пример показывает, что получится, если этот запрос действительно запустить на выполнение:
Model
--------
СХ3000
СХ3010
СХ3020
МХ3030
МХ3020
МХ3030
Теперь известно, каких товаров в скором времени не будет у вас на складе. Рекламу этих товаров следует на время, по возможности, свернуть.
Этот вид вложенного запроса предполагает, что подзапрос возвращает единственный столбец, и тип данных для этого столбца совпадает с типом данных аргумента, находящегося перед ключевым словом IN.
Подзапросы, перед которыми стоит ключевое слово NOT IN
Запрос с ключевым словом IN, приведенный в предыдущем разделе, помог руководству фирмы узнать, какие товары нельзя будет продавать. Хотя это и ценная информация, но на ней много не заработаешь. А вот что действительно надо знать руководству Zetec — какие товары молено будет активно продавать. Руководство фирмы хочет продвигать именно те товары, в состав которых мониторы не входят. Такую информацию можно получить с помощью подзапроса, перед которым стоит ключевое слово NOT IN:
SELECT Model
FROM COMP_USED
WHERE Model NOT IN
(SELECT Model
FROM COMP_USED
WHERE CompID IN
(SELECT CompID
FROM COMPONENT
WHERE CompType = 'Monitor')) ;
В результате выполнения этого оператора получаем следующее:
Model
--------
РХ3040
РВ3050
РХ3040
РВ3050
Здесь надо сказать о двух моментах.
- В этом запросе имеются два уровня вложенности. Два подзапроса — это в точности оператор предыдущего запроса. Теперь он вложен во внешний замыкающий оператор SELECT. Он принимает список товаров, в состав которых входят мониторы. Перед SELECT стоит другое ключевое слово — NOT EM. В результате действия внешнего оператора создается еще один список. В нем перечислены модели всех продуктов, за исключением тех, в состав которых входят мониторы.
- В получившейся виртуальной таблице некоторые строки могут повторяться. Причина повторений следующая. Название товара, собранного из нескольких компонентов, среди которых нет мониторов, встречается в нескольких строках таблицы COMPJUSED. И каждой такой строке соответствует отдельная строка в получившейся виртуальной таблице.
В этом примере количество строк не является проблемой, потому что получившаяся виртуальная таблица является короткой. Однако в реальной жизни такая таблица может состоять из сотен и тысяч строк. Чтобы не было путаницы, повторяющиеся строки необходимо убирать. Это сделать достаточно легко, если в запрос вставить ключевое слово DISTINCT (различный). Тогда в виртуальную таблицу будут добавляться только те строки, которые отличаются от уже имеющихся:
SELECT DISTINCT Model
FROM COMP_USED
WHERE Model NOT IN
(SELECT Model
FROM COMP_USED
WHERE CompID IN
(SELECT CompID
FROM COMPONENT
WHERE CompType = 'Monitor')) ;
Как и ожидалось, результат получился следующий:
Model
--------
РХ3040
РВ3050