SQL Server 2005 引入的 CROSS APPLY 與 INNER JOIN 都能關聯表,但適用場景本質不同。本文通過對比分析,闡明 CROSS APPLY 的獨特價值——表值函數調用與分組後逐行處理。
-- INNER JOIN:表與表關聯
SELECT * FROM TableA a INNER JOIN TableB b ON a.id = b.a_id;
-- CROSS APPLY:表與表值函數/子查詢關聯,右側可引用左側列
SELECT * FROM TableA a CROSS APPLY fn_GetRelated(a.id);
-- OUTER APPLY:類似 LEFT JOIN,右側無結果也保留左側行
SELECT * FROM TableA a OUTER APPLY fn_GetRelated(a.id);
| 特性 | INNER JOIN | CROSS APPLY |
|---|---|---|
| 右側對象 | 表/視圖/子查詢 | 表值函數/關聯子查詢 |
| 引用左側列 | ON 條件中 | 函數參數/子查詢 WHERE 中 |
| 逐行執行 | 否(集合運算) | 是(對左側每行單獨執行右側) |
| 無匹配行 | 過濾掉 | 過濾掉(OUTER APPLY 保留) |
需求:查詢每個部門薪資最高的 2 名員工。
SELECT d.DeptName, e.EmpName, e.Salary
FROM Department d
CROSS APPLY (
SELECT TOP 2 EmpName, Salary
FROM Employee
WHERE DeptID = d.DeptID
ORDER BY Salary DESC
) e;
-- 需窗口函數 ROW_NUMBER() OVER (PARTITION BY DeptID ORDER BY Salary DESC)
-- 或相關子查詢 + NOT EXISTS,可讀性差、性能往往較差
-- 假設函數 fn_SplitString(@str, @delim) 返回表 (id, val)
SELECT t.id, s.val
FROM MyTable t
CROSS APPLY fn_SplitString(t.csv_col, ',') s;
-- INNER JOIN 無法直接調用函數並傳遞當前行列值
CROSS APPLY 對左側每行執行右側邏輯,左側行數大時可能較慢Nested Loops + Table Valued FunctionCROSS APPLY 是唯一/最優選擇