需求:依多欄位分組,取每組前 N 筆 (通常 N=1)。提供兩種標準寫法並分析適用場景。
SELECT a.*
FROM table1 a
WHERE a.column1 IN (
SELECT MAX(column1)
FROM table1
GROUP BY a.column2, column3
);
a.column2 (需重寫為關聯子查詢或 JOIN)。IN 列表膨脹效能劣化。WITH ranked AS (
SELECT
NYR, QYZX_DM, FXSP_XH, SPBM_DLJ, WBSP_GG, JGLX, JZJG, MAX(SJGX_SJ),
ROW_NUMBER() OVER (PARTITION BY NYR ORDER BY NYR) AS rn
FROM WD_O_T_IC_SPSJ_FX
GROUP BY NYR, QYZX_DM, FXSP_XH, SPBM_DLJ, WBSP_GG, JGLX, JZJG
)
SELECT *
FROM ranked
WHERE rn = 1;
修正:原文 WHERE rowno=1 置於 CTE 內部會報錯,必須在外層篩選。
| 維度 | IN 子查詢 | ROW_NUMBER() |
|---|---|---|
| 可讀性 | 簡單分組佳 | 通用、支援多欄排序 |
| 索引利用 | 依賴 MAX() 索引掃描 | 需 (PARTITION BY, ORDER BY) 複合索引 |
| 大資料量 | 易產生大量邏輯讀 | 單次掃描 + 排序,較穩定 |
| 取前 N (N>1) | 極難寫 | 直接 WHERE rn <= N |
| 相容性 | 所有版本 | SQL Server 2005+ |
ROW_NUMBER(),彈性最高。INDEX (partition_cols, order_cols) INCLUDE (select_cols) 避免 Key Lookup。TOP 1 WITH TIES 替代。