需求:將連續且相同的狀態變更記錄合併,不連續或不同狀態保留。關鍵在於區分「連續」與「非連續」的相同群組。
DECLARE @TestData TABLE (ID INT, Col1 VARCHAR(20), Col2 VARCHAR(20)); INSERT INTO @TestData VALUES (1,'New','Approved'), (2,'Approved','Commited'), (3,'Commited','In Progress'), (4,'New','Approved'), (5,'New','Approved'), (6,'New','Approved'), (7,'Approved','Removed');
ID 1,4,5,6 皆為 New→Approved,但 1 與 4-6 不連續,需分兩組;4-6 連續合併為一組。
WITH Ranked AS (
SELECT
ID, Col1, Col2,
RANK() OVER (PARTITION BY Col1+Col2 ORDER BY ID) AS Rnk
FROM @TestData
),
Grouped AS (
SELECT
ID, Col1, Col2,
ID - Rnk AS GrpKey -- 連續相同記錄的 ID 與 Rnk 同步遞增,差值固定
FROM Ranked
)
SELECT
MIN(ID) AS StartID, Col1, Col2, COUNT(*) AS MergeCount
FROM Grouped
GROUP BY Col1, Col2, GrpKey
ORDER BY StartID;
PARTITION BY Col1+Col2 將相同狀態變更分組(1,4,5,6 同組)。RANK() ORDER BY ID 產生組內排名 R:1→1, 4→2, 5→3, 6→4。ID - R 恆定(4-2=2, 5-3=2, 6-4=2)。ID - R = 0,與連續組差值不同,自然分組。Col1, Col2, ID-R 分組,取 MIN(ID) 即得合併後起始 ID。| StartID | Col1 | Col2 | MergeCount |
|---|---|---|---|
| 1 | New | Approved | 1 |
| 2 | Approved | Commited | 1 |
| 3 | Commited | In Progress | 1 |
| 4 | New | Approved | 3 |
| 7 | Approved | Removed | 1 |
將 RANK() 改為 ROW_NUMBER(),邏輯不變,ID - RN 仍能識別連續段。
此技巧屬於「間隙與島嶼」經典模式,掌握 ROW_NUMBER() 差值分組思維,可解決多種連續性分析問題。