OpenU.Ru
Подзапрос – это запрос, результат которого используется внутри другого запроса. В большинстве случаев (кроме использования специальных булевых операторов – см. ниже) требуется, чтобы результатом подзапроса было одно поле. Например, пусть требуется вывести список товаров, проданных на сумму свыше 90000:
SELECT GName FROM Goods WHERE GNum in (SELECT GNum FROM Sells WHERE SSum>90000)
В результате получим:
Gname |
Сахар |
Мыло |
В результате подзапроса выбрано одно поле GNum из таблицы Sells, на совпадение, со значениями которого сравнивается поле GNum из таблицы Goods.
Для работы с подзапросами также используются реляционные операторы, булевы операторы, и специальные операторы EXIST, ANY, ALL и SOME.
Оператор EXISTS в запросе используется в тех случаях, когда необходимо проверить результат подзапроса на его существование, т.е. выбрал подзапрос что-нибудь из базы данных или нет. Он может работать автономно в предикате или в комбинации с другими логическими выражениями, использующими булевы операторы AND, OR, и NOT. Оператор EXISTS берет подзапрос как аргумент и оценивает его как верный, если тот производит любой вывод, или как неверный, если тот не делает этого. Например, пусть необходимо выбрать только те товары, которые были проданы на сумму выше, чем цена. Напишем данный запрос с помощью оператора EXISTS:
SELECT Goods.GName FROM Goods WHERE EXISTS (SELECT * FROM Sells WHERE Sells.SSum>Goods.Gprice AND Sells.GNum=Goods.GNum)
Получим:
Gname |
Сахар |
Мука |
Мыло |
Пиво |
Фен «Philips» |
В отличие от других операторов EXISTS выполняется только один раз для каждой строки таблицы, указанной во внешнем запросе.
EXISTS всегда можно заменить на оператор IN, что, однако, приводит к замедлению работы запроса.
Оператор ANY также используется с подзапросами, но в отличие от EXISTS, он работает с реляционными операторами. Оператор ANY берет все значения, выведенные подзапросом, и оценивает их как верные, если любое из них удовлетворяет условию.
Например, выведем только те группы товаров, для которых определены товары:
SELECT * FROM GoodsTypes WHERE GTNum=ANY(SELECT GoodsTypesFROM Goods)
Также как и оператор ANY, оператор ALL работает с реляционными операторами. Он работает таким образом, что предикат является верным, если каждое значение, выбранное подзапросом, удовлетворяет условию в предикате внешнего запроса.
Например, пусть необходимо выбрать только тех покупателей, которые не совершали покупки 05.05.01, т.е. если покупка совершена этой датой, то этого покупателя включать в результат запроса не нужно. Для этого напишем запрос с использованием ALL:
SELECT * FROM Buyers WHERE BNum<>ALL(SELECT BNum FROM Sells WHERE SDate="05.05.01")
Этот запрос работает следующим образом. Сначала подзапрос в ALL выбирает номера всех покупателей, совершивших покупки 05.05.01. Затем он находит номера покупателей не равных выбранным и выводит их в результате:
BNum | BName | BTown |
1 | Дельта | 1 |
5 | Москва | 3 |
Операторы ANY и ALL допускают использование EXISTS для альтернативного формулирования такого же запроса.
Оператор ALL редко используется со знаком «равно», т.к. предикат может быть верным, если сравниваемое значение равно для всех, т.е. все записи должны быть идентичны. Например, если в предыдущем запросе вместо знака неравенства поставить равенство, то вывод запроса осуществится только в том случае, если номера покупателей, совершивших покупки в этот день, будут совпадать. Основное применение оператор ALL находит со знаками неравенства.
Содержание