使用純量子查詢或多重值子查詢
純量子查詢是外部查詢之內的內部 SELECT 陳述式,撰寫成只傳回單一值。 在允許單一值運算式的外部 T-SQL 陳述式中,任何地方都可能使用純量子查詢,例如 SELECT 子句、WHERE 子句、HAVING 子句,甚至是 FROM 子句。 也可以用在資料修改陳述式中,例如 UPDATE 或 DELETE。
顧名思義,多重值子查詢可以傳回一個以上的資料列。 不過,仍然只傳回單一資料行。
純量子查詢
假設您想要取得最後一筆訂單的詳細資料,並假定此訂單具有最高的 SalesOrderID 值。
若要尋找最高的 SalesOrderID 值,您可以使用下列查詢:
SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader
此查詢傳回單一值,代表 SalesOrderHeader 資料表中 OrderID 的最高值。
若要取得此訂單的詳細資料,您可能需要根據上述查詢所傳回的任何值來篩選 SalesOrderDetails 資料表。 為了完成此工作,您可以在取出訂單詳細資料的查詢中,在 WHERE 子句之內巢狀查詢,以取得最大的 SalesOrderID。
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 來撰寫查詢。
最後,在某些情況下,內部查詢需要執行的作業,遠比範例中的簡單擷取複雜得多。 使用 JOIN 來重寫複雜的子查詢可能很困難。 許多 SQL 開發人員發現子查詢最適合複雜的處理,因為可讓您將處理分割成較小的步驟。