子查詢分「標準」 (執行一次回傳結果給外層) 與「相關」 (外層每列執行一次)。本文聚焦巢狀標準子查詢,以 AdventureWorks 範例庫示範「找出銷售平墊圈的業務員」,展示由內而外的思考路徑與由外而內的撰寫技巧。
四張表關聯:Person.Contact (姓名) → HumanResources.Employee (員工) → Sales.SalesOrderHeader (訂單主檔) → Sales.SalesOrderDetail (訂單明細) → Production.Product (產品)。需找出銷售產品編號以 FW% 開頭 (平墊圈) 的業務員姓名。
SELECT ProductID FROM Production.Product WHERE ProductNumber LIKE 'FW%' → 取得目標產品 ID 清單。SELECT SalesOrderID FROM Sales.SalesOrderDetail WHERE ProductID IN (上層結果) → 含目標產品的訂單明細 ID。SELECT SalesPersonID FROM Sales.SalesOrderHeader WHERE SalesOrderID IN (上層結果) → 負責這些訂單的業務員 ID。SELECT DISTINCT LastName, FirstName FROM Person.Contact JOIN HumanResources.Employee ON ContactID WHERE EmployeeID IN (上層結果) → 業務員姓名。USE AdventureWorks; GO
SELECT DISTINCT c.LastName, c.FirstName
FROM Person.Contact c
JOIN HumanResources.Employee e ON e.ContactID = c.ContactID
WHERE e.EmployeeID IN (
SELECT SalesPersonID
FROM Sales.SalesOrderHeader
WHERE SalesOrderID IN (
SELECT SalesOrderID
FROM Sales.SalesOrderDetail
WHERE ProductID IN (
SELECT ProductID
FROM Production.Product p
WHERE ProductNumber LIKE 'FW%'
)
)
); GO
IN (SELECT ...) 可直接替代純量值,自然形成巢狀結構。IN 轉為 JOIN 或 EXISTS 執行;若資料量大,建議改寫為 JOIN 或 APPLY 並觀察執行計畫。當查詢條件分散於多層關聯表,且中間層僅作為「橋樑」不需輸出欄位時,巢狀子查詢語意最清晰;若需輸出中間層欄位或進行複雜聚合,轉用 JOIN / CTE 較佳。