2016-01-20 105 views
1

假設我有以下記錄:TSQL計數連續記錄

KeyCol  ColA  ColB 
------------------------ 
1   1  A 
2   2  B 
3   2  B 
4   2  C 
5   2  B 
6   1  A 
7   2  B 
8   2  B 

我想算有這個結果可樂COLB相同值的連續記錄

Col A  ColB  Start Count 
--------------------------------- 
1   A  1  1 
2   B  2  2 
2   C  4  1 
2   B  5  1 
1   A  6  1 
2   B  7  2 

有很多相似關於分組和計數的問題,但我沒有看到如何將它翻譯成這個問題。特別是許多其他示例沒有明確的鍵列。

我曾嘗試使用的分區函數計算的連續記錄數,並從那裏:

SELECT KeyCol, ColA, ColB 
     ,ROW_NUMBER() OVER 
      ( PARTITION 
       BY ColA, ColB 
       ORDER BY KeyCol 
      ) as RowNo 
FROM MyTable 

然而,這會產生這樣的結果:

KeyCol Col A  ColB  RowNo 
--------------------------------- 
1   1   A  1 
2   2   B  1 
3   2   B  2 
4   2   C  1 
5   2   B  3 (Needs to be 1) 
6   1   A  2 (Needs to be 1) 
7   2   B  4 (Needs to be 1) 
8   2   B  5 (Needs to be 2) 

正如你所看到的,即使記錄不連續,所有同一ColA,ColB的行號也會增加。

非常感謝!

+0

您嘗試過什麼嗎?如果你有,編輯查詢到你的問題。 –

+1

嗨TT,感謝您的評論。我剛剛添加了一個我嘗試過的查詢。 – Roeland

回答

4

這是一個Gaps and Islands problem。您需要使用排名函數來確定ColB具有相同值的組(島)。下面的查詢:

SELECT KeyCol, 
     ColA, 
     ColB, 
     GroupBy = ROW_NUMBER() OVER(ORDER BY KeyCol) - 
        ROW_NUMBER() OVER(PARTITION BY ColA, ColB ORDER BY KeyCol) 
FROM dbo.T 
ORDER BY KeyCol; 

你會得到輸出:

KeyCol  ColA  ColB GroupBy 
----------------------------------------- 
1   1  A   0 
2   2  B   1 
3   2  B   1 
4   2  C   3 
5   2  B   2 
6   1  A   4 
7   2  B   3 
8   2  B   3 

正如你所看到的,這個標識您的島嶼,其中兩個(或更多)連續的行有可樂COLB相同的值,您將在列GroupBy中獲得相同的值。

一旦你有了它,它是一個簡單的例子,它可以得到你需要的輸出。給出最後一個查詢(帶有樣本數據):

DECLARE @T TABLE (KeyCol INT, ColA INT, ColB CHAR(1)); 
INSERT @T (KeyCol, ColA, ColB) 
VALUES 
    (1, 1, 'A'), (2, 2, 'B'), (3, 2, 'B'), (4, 2, 'C'), 
    (5, 2, 'B'), (6, 1, 'A'), (7, 2, 'B'), (8, 2, 'B'); 

WITH RankedData AS 
( SELECT KeyCol, 
      ColA, 
      ColB, 
      GroupBy = ROW_NUMBER() OVER(ORDER BY KeyCol) - 
         ROW_NUMBER() OVER(PARTITION BY ColA, ColB ORDER BY KeyCol) 
    FROM @T 
) 
SELECT ColA, 
     ColB, 
     Start = MIN(KeyCol), 
     [Count] = COUNT(*) 
FROM RankedData 
GROUP BY ColA, ColB, GroupBy 
ORDER BY Start; 
+0

嗨加雷斯,很好的回答,謝謝!我只有一個問題:你能否在KeyCol自身存在差距的情況下使用它。所以說第三個記錄從KeyCol = 4開始。這是我面臨的情況。只是好奇,我仍然可以通過創建一個連續的KeyCol值創建表的中間步驟來使用您的答案。 – Roeland

+0

@Roeland對不起,我一直犯這個錯誤....我現在編輯了答案,所以現在不用'KeyCol - ROW_NUMBER()...'來生成標識符,它現在使用一個進一步的排序函數來生成無間隙的序列來替換KeyCol。 – GarethD

+0

它現在看起來非常簡單,手頭上有答案:)非常感謝Gareth,無法夢想這樣一個迅速的解決方案! – Roeland