首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 巢狀子查詢實戰:從內而外建構多表關聯查詢

     編輯:關於SqlServer

子查詢類型回顧

  • 標準子查詢:執行一次,結果傳給外層。
  • 相關子查詢:外層每列執行一次,參考外層欄位。
  • 巢狀子查詢:子查詢中再包含子查詢,層層遞進。

實戰情境

需求:列出銷售「平墊圈」產品的業務人員姓名。資料分散四表:

  • Person.Contact(姓名)
  • HumanResources.Employee(員工編號 ↔ ContactID)
  • Sales.SalesOrderHeader(訂單 ↔ SalesPersonID)
  • Sales.SalesOrderDetail(訂單明細 ↔ ProductID)
  • Production.Product(產品編號 ↔ ProductNumber LIKE 'FW%')

由內而外建構思維

  1. 最內層:找出平墊圈產品 SELECT ProductID FROM Production.Product WHERE ProductNumber LIKE 'FW%'
  2. 第二層:找出含該產品的訂單 SELECT SalesOrderID FROM Sales.SalesOrderDetail WHERE ProductID IN (...)
  3. 第三層:找出處理該訂單的業務 SELECT SalesPersonID FROM Sales.SalesOrderHeader WHERE SalesOrderID IN (...)
  4. 最外層:聯結員工與聯絡人取得姓名。

完整巢狀子查詢 SQL

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
            WHERE ProductNumber LIKE 'FW%'
        )
    )
);
GO

等效 JOIN 寫法(效能通常更好)

SELECT DISTINCT c.LastName, c.FirstName
FROM Person.Contact c
JOIN HumanResources.Employee e ON e.ContactID = c.ContactID
JOIN Sales.SalesOrderHeader soh ON soh.SalesPersonID = e.EmployeeID
JOIN Sales.SalesOrderDetail sod ON sod.SalesOrderID = soh.SalesOrderID
JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE p.ProductNumber LIKE 'FW%';

巢狀子查詢 vs JOIN 比較

面向巢狀子查詢JOIN
可讀性邏輯層次分明,符合「由內而外」思維關聯關係扁平,需熟悉資料模型
效能舊版優化器可能產生重複掃描現代優化器通常轉為相同計畫
除錯可逐層獨立執行驗證需整體執行
適用場景階層式過濾、EXISTS/NOT EXISTS、動態 SQL 組裝標準多表關聯、報表查詢

最佳實務建議

  • 優先使用 JOIN,語意清晰且優化器成熟。
  • 需「存在性檢查」時用 EXISTS (SELECT 1 FROM ...),避免 IN (SELECT ...) 產生 NULL 陷阱。
  • 巢狀層次超過 3 層時,考慮使用 CTE (Common Table Expression) 拆解邏輯:
WITH fw_products AS (
    SELECT ProductID FROM Production.Product WHERE ProductNumber LIKE 'FW%'
),
fw_orders AS (
    SELECT DISTINCT SalesOrderID FROM Sales.SalesOrderDetail WHERE ProductID IN (SELECT ProductID FROM fw_products)
),
fw_salespersons AS (
    SELECT DISTINCT SalesPersonID FROM Sales.SalesOrderHeader WHERE SalesOrderID IN (SELECT SalesOrderID FROM fw_orders)
)
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 fw_salespersons);

結語

巢狀子查詢是 SQL 邏輯分解的有力工具,但現代開發應以 JOIN 與 CTE 為主,保持查詢可維護與高效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved