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

SQL Server 相關子查詢深度解析:原理、效能與實戰範例

     編輯:關於SqlServer

什麼是相關子查詢?

相關子查詢 的核心特徵:子查詢參考了外部查詢的欄位,導致子查詢必須針對外部查詢的每一列重新執行一次。

-- 經典子查詢:獨立執行一次,結果供外部使用
SELECT * FROM Orders WHERE CustomerID IN (SELECT CustomerID FROM Customers WHERE City = 'London');

-- 相關子查詢:外部每一列都要執行一次子查詢
SELECT OrderID, OrderDate,
       (SELECT COUNT(*) FROM OrderDetails od WHERE od.OrderID = o.OrderID) AS DetailCount
FROM Orders o;

執行機制與效能特性

  • 執行順序:由內而外,但相關子查詢需對外部結果集逐列迭代
  • 效能影響:外部結果集越大、子查詢越複雜,效能下降越明顯
  • 優化機會:良好索引、精簡邏輯、避免不必要的相關引用

⚠ 寫得好的相關子查詢有時比多重 JOIN + 暫存表更快,關鍵在於邏輯精簡與索引支援。

實戰範例:累計銷售總額報表

建立範例資料

CREATE TABLE SalesHistory (
    SaleID INT IDENTITY(1,1),
    Product VARCHAR(30),
    SaleDate SMALLDATETIME,
    SalePrice MONEY
);

-- 插入 300 筆測試資料(略)

相關子查詢產生累計總額

SELECT 
    sh1.Product,
    sh1.SaleDate,
    sh1.SalePrice,
    (SELECT SUM(sh2.SalePrice) 
     FROM SalesHistory sh2 
     WHERE sh2.Product = sh1.Product 
       AND sh2.SaleDate <= sh1.SaleDate) AS RunningTotal
FROM SalesHistory sh1
ORDER BY sh1.Product, sh1.SaleDate;

邏輯解析:對每一筆銷售記錄,子查詢計算「同產品且日期不晚於該筆」的銷售額總和,形成累計值。

相關子查詢 vs 替代方案

方案優點缺點適用場景
相關子查詢 語意清晰、單一陳述式完成、無需臨時物件 大資料集效能風險 報表累計、逐列比較、邏輯難以 JOIN 表達
視窗函數 (SUM() OVER) 效能極佳、語法標準、單次掃描 SQL Server 2012+ 才完整支援 現代版本首選方案
暫存表 + 迴圈/游標 可控制批次大小、適合極複雜邏輯 程式碼冗長、維護困難 舊版本、極特殊業務邏輯

優化檢查清單

  1. 子查詢 WHERE 條件欄位是否有索引?
  2. 能否改寫為 JOIN 或 APPLY (CROSS/OUTER APPLY)?
  3. 外部結果集能否預先過濾縮小範圍?
  4. 是否誤用了 SELECT * 導致不必要的資料傳輸?

進階技巧:CROSS APPLY 重構

SELECT sh1.Product, sh1.SaleDate, sh1.SalePrice, ca.RunningTotal
FROM SalesHistory sh1
CROSS APPLY (
    SELECT SUM(sh2.SalePrice) AS RunningTotal
    FROM SalesHistory sh2
    WHERE sh2.Product = sh1.Product
      AND sh2.SaleDate <= sh1.SaleDate
) ca
ORDER BY sh1.Product, sh1.SaleDate;

CROSS APPLY 語意等同相關子查詢,但更易閱讀、優化器處理更佳,推薦用於 SQL Server 2005+ 環境。

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