Открытая коллекция знаний

OpenU.Ru

Язык запросов SQL. DML.



Подзапросы SQL

Подзапрос – это запрос, результат которого используется внутри другого запроса. В большинстве случаев (кроме использования специальных булевых операторов – см. ниже) требуется, чтобы результатом подзапроса было одно поле. Например, пусть требуется вывести список товаров, проданных на сумму свыше 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 находит со знаками неравенства.

Содержание