Использование скалярных или многозначных вложенных запросов.
Скалярный вложенный запрос — это внутренняя инструкция SELECT во внешнем запросе, написанная для возврата одного значения. Скалярные вложенные запросы могут использоваться в любом месте внешней инструкции T-SQL, где разрешено однозначное выражение, например в предложении SELECT, предложении WHERE, предложении HAVING или даже предложении FROM. Их также можно использовать в инструкциях изменения данных, таких как UPDATE или DELETE.
Многозначные вложенные запросы, как следует из их названия, могут возвращать более одной записи. Однако они по-прежнему возвращают один столбец.
скалярные вложенные запросы;
Предположим, вы хотите получить сведения о последнем размещенном заказе, предполагая, что у него самое высокое значение SalesOrderID.
Чтобы найти наибольшее значение SalesOrderID, можно использовать следующий запрос:
SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader
Этот запрос возвращает одно значение, указывающее наибольшее значение для OrderID в таблице SalesOrderHeader.
Чтобы получить сведения об этом заказе, может потребоваться отфильтровать таблицу SalesOrderDetails на основе значения, возвращенного приведенным выше запросом. Эту задачу можно выполнить путем вложения запроса для получения максимального значения SalesOrderID в предложение WHERE запроса, извлекающего сведения о заказе.
SELECT SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderDetail
WHERE SalesOrderID =
(SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader);
Для написания скалярного вложенного запроса учитывайте следующие рекомендации:
- Чтобы обозначить запрос как вложенный, заключите его в круглые скобки.
- Transact-SQL поддерживает несколько уровней вложенных запросов. В этом модуле мы будем рассматривать только двухуровневые запросы (один внутренний запрос в рамках одного внешнего запроса). Однако поддерживается до 32 уровней.
- Если вложенный запрос не возвращает строки (пустой набор), результатом вложенного запроса будет NULL. Если в вашем сценарии нет возвращаемых записей, убедитесь, что внешний запрос может справиться с обработкой значения NULL наряду с другими ожидаемыми результатам.
- Внутренний запрос обычно должен возвращать один столбец. Выбор нескольких столбцов во вложенном запросе почти всегда является ошибкой. Единственное исключение, если вложенный запрос вводится с помощью ключевого слова EXISTS.
Скалярный вложенный запрос можно использовать в любом расположении запроса, где ожидается значение, включая список SELECT. Например, можно расширить запрос, извлекающий сведения о самом последнем заказе, для включения среднего количества заказанных товаров, чтобы можно было сравнить заказанное количество в самом последнем заказе со средним значением для всех заказов.
SELECT SalesOrderID, ProductID, OrderQty,
(SELECT AVG(OrderQty)
FROM SalesLT.SalesOrderDetail) AS AvgQty
FROM SalesLT.SalesOrderDetail
WHERE SalesOrderID =
(SELECT MAX(SalesOrderID)
FROM SalesLT.SalesOrderHeader);
Многозначные вложенные запросы
Многозначный вложенный запрос хорошо подходит для возврата результатов с помощью оператора IN. В следующем гипотетическом примере возвращаются значения CustomerID, SalesOrderID для всех заказов, размещенных клиентами в Канаде.
SELECT CustomerID, SalesOrderID
FROM Sales.SalesOrderHeader
WHERE CustomerID IN (
SELECT CustomerID
FROM Sales.Customer
WHERE CountryRegion = 'Canada');
Если бы в этом примере мы выполняли только внутренний запрос, был бы возвращен столбец значений CustomerID со строкой для каждого клиента в Канаде.
Во многих случаях многозначные вложенные запросы можно легко написать с помощью соединений. Например, в запросе ниже используется соединение для возврата тех же результатов, что и в предыдущем примере:
SELECT c.CustomerID, o.SalesOrderID
FROM Sales.Customer AS c
JOIN Sales.SalesOrderHeader AS o
ON c.CustomerID = o.CustomerID
WHERE c.CountryRegion = 'Canada';
Как же выбрать, написать запрос, включающий несколько таблиц, используя оператор JOIN, или вложенный запрос? В некоторых случаях это зависит только от того, что вам больше нравится. Большинство вложенных запросов, которые легко преобразовать в запросы с JOIN, фактически преобразуются на внутреннем уровне. Нет реальной разницы, какой способ вы выберете для написания таких запросов.
Необходимо учитывать одно ограничение. При использовании вложенного запроса результаты, возвращаемые клиенту, могут содержать только столбцы из внешнего запроса. Поэтому, если необходимо вернуть столбцы из обеих таблиц, необходимо написать запрос с помощью оператора JOIN.
Наконец, существуют ситуации, когда внутренний запрос должен выполнять гораздо более сложные операции, чем простые извлечения в наших примерах. Перезапись сложных вложенных запросов с помощью оператора JOIN может оказаться трудной задачей. Многие разработчики SQL предпочитают использовать вложенные запросы для сложной обработки, так как они позволяют разбить обработку на более мелкие этапы.