Использование подзапросов
Часто невозможно решить поставленную задачу путем использования одного запроса. Это особенно актуально в тех случаях, когда при использовании условия поиска в предложении WHERE
Сравниваемое значение> <оператор> <значение, с которым сравнивать>
значение, с которым надо сравнивать,
заранее не определено и должно быть вычислено в момент выполнения оператора SELECT.Другой причиной, которая должна побудить к использованию вложенных подзапросов, является то, что во многих случаях значение, с которым надо сравнивать, должно представлять собой не одно, а несколько значений.
Внутренний подзапрос представляет собой также оператор SELECT и кодирование его предложений подчиняется тем же правилам, что и для основного оператора SELECT.
В общем случае оператор SELECT с подзапросом имеет вид
SELECT .. .
FROM ...
WHERE Сравниваемое значение> <оператор> SELECT ...
FROM ...
WHERE ...
Пример.
Выдать все даты, на которые приходится максимальный отпуск товаров (результат на рис. 25.36).SELECT KOLVO, DAT_RASH FROM RASHOD
WHERE KOLVO = (SELECT MAX(KOLVO) FROM RASHOD
KOLVO
DAT_RASH
1
10.01.97
Puc. 25.36.
Сначала нужно найти количество максимального отпуска товаров, поскольку это значение неизвестно. Это и делает внутренний подзапрос (SELECT MAX(KOLVO) FROM RASHOD )
Далее выполняется основной запрос, как если бы он был записан так:
SELECT KOLVO, DAT_RASH FROM RASHOD WHERE KOLVO = 4000
Пример.
Усложним предыдущий пример. Определить дату, когда со склада было отгружено максимальное количество товара, и реквизиты покупателя, который этот товар купил (результат на рис. 25.37).SELECT R.KOLVO, R.DAT_RASH, P.POKUP, P.GOROD, P.ADRES
FROM RASHOD R, POKUPATELI P
WHERE (R.POKUP = P.POKUP) AND
KOLVO =(SELECT MAX(KOLVO)
FROM RASHOD
)
По сравнению с предыдущим примером в запрос включено внутреннее соединение таблиц RASHOD и POKUPATELI.
ЗАМЕЧАНИЕ.
Распространенной ошибкой является использование вложенного оператора SELECT, который вместо единичного значения способен возвращать список значений.Выше по тексту есть абзац: Другой причиной, которая должна побудить к использованию вложенных подзапросов, является то, что во многих случаях значение, с которым сравнивать, должно представлять собой не одно, а несколько значений. Поясним, почему этот абзац нельзя распространять на следующий пример.
Пример.
Найти в таблице POKUPATELI покупателя, у которого поле GOROD содержит "С-Петербург" и выдать все осуществленные им покупки товаров, из таблицы RASHOD. Может быть написан следующий потенциально ошибочный запрос (результат на рис. 25.38).SELECT R.DAT_RASH, R.TOVAR, R.KOLVO, R.POKUP FROM RASHOD R
WHERE R.POKUP = (SELECT POK.POKUP FROM POKUPATELI РОК
WHERE UPPER(РОК.GOROD) = 'С-ПЕТЕРБУРГ '
)
Хотя для значения "С-Петербург" и был выдан корректный результат, такой запрос потенциально ошибочен, поскольку способен возвращать несколько значений; например, если поменять "С-Петербург" на "Москва", получим уведомление об ошибке (рис. 25.39)
SELECT R.DAT_RASH, R.TOVAR, R.KOLVO, R.POKUP FROM RASHOD R
WHERE R.POKUP = (SELECT POK.POKUP FROM POKUPATELI РОК
WHERE UPPER(РОК.GOROD) = 'МОСКВА' )