Подзапрос – это оператор SELECT, включенный в другие запросы. Подзапросы применяются для разбивки сложного запроса на серию логических этапов. Их применение эффективно, если запрос использует записи, возвращенные другим запросом.
Существует два вида подзапросов.
1) Вложенные подзапросы – возвращают единственное значение либо список значений. Вложенный запрос выполняется один раз, а затем результирующее значение используется во внешнем запросе.
Например, чтобы определить имена заказчиков, разместивших заказы в последний учетный день, можно воспользоваться следующим запросом:
Select CustomerID
From Sales.SalesOrderHeader
Where OrderDate =
(SELECT Max(OrderDate) From Sales. SalesOrderHeader)
Выполнение этого запроса осуществляется в два этапа: на первом – осуществляется выполнение подзапроса, как самостоятельного запроса, который возвращает значение, используемое на втором этапе при выполнении внешнего запроса.
В результате получаем имена и фамилии, которые могут быть использованы в подзапросе для получения полного имени заказчика:
SELECT FirstName + ' ' + LastName AS 'CustomerName'
FROM Sales.vIndividualCustomer
WHERE CustomerID in
(SELECT CustomerID
FROM Sales.SalesOrderHeader
WHERE OrderDate=
(SELECT Max(OrderDate) FROM Sales. SalesOrderHeader))
Такой запрос может быть оформлен и в виде соединения таблиц. Такие запросы обрабатываются значительно быстрее, поэтому если выполнение запроса не требуется выполнять в несколько этапов, использование подзапросов не обязательно.
2) Связанные подзапросы – используются данные внешнего запроса, причем связанный запрос выполняется один раз для каждой записи внешнего запроса.
Например, для определения списка заказчиков, заказавших за один раз более 300 единиц товара, необходимо выполнить следующий запрос:
SELECT SalesOrderID, CustomerID
FROM Sales.SalesOrderHeader oh
WHERE 300 < (SELECT sum(OrderQty)
FROM Sales.SalesOrderDetail od
WHERE od.SalesOrderID = oh.SalesOrderID)
В связанных подзапросах, чтобы различать имена таблиц необходимо применять их псевдонимы. В примере для таблицы SalesOrderHeader определен псевдоним oh, а для SalesOrderDetail – od.
Однако использование связанных подзапросов неэффективно, лучше преобразовывать их в соединения таблиц, что позволяет оптимизатору запросов выбирать наилучший способ обработки данных.
Например, следующий запрос для каждого товара отображает сведения о самом крупном его заказе: количество заказанного товара и номер заказа.
SELECT Name, OrderQty, SalesOrderID
FROM Production.Product p
INNER JOIN Sales.SalesOrderDetail od1 ON od1.ProductID=p.ProductID