TSQL 计数连续记录

TSQL Count Consecutive records

假设我有以下记录:

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

我想用这个结果计算 ColA 和 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

有很多关于分组和计数的类似问题,但我看不出如何将其翻译成这个问题。特别是许多其他示例没有显式键列。

我已经尝试使用 PARTITION 函数来计算连续记录的数量并从那里获取:

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 的行号都会增加,即使记录不连续也是如此。

非常感谢!

这是一个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   

如您所见,这标识了您的岛屿,其中两个(或更多)连续行具有相同的 ColA 和 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;