TSQL计数连续记录
假设我有以下记录: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的行号也会增加。
非常感谢!
这是一个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;
嗨加雷斯,很好的回答,谢谢!我只有一个问题:你能否在KeyCol自身存在差距的情况下使用它。所以说第三个记录从KeyCol = 4开始。这是我面临的情况。只是好奇,我仍然可以通过创建一个连续的KeyCol值创建表的中间步骤来使用您的答案。 – Roeland
@Roeland对不起,我一直犯这个错误....我现在编辑了答案,所以现在不用'KeyCol - ROW_NUMBER()...'来生成标识符,它现在使用一个进一步的排序函数来生成无间隙的序列来替换KeyCol。 – GarethD
它现在看起来非常简单,手头上有答案:)非常感谢Gareth,无法梦想这样一个迅速的解决方案! – Roeland
您尝试过什么吗?如果你有,编辑查询到你的问题。 –
嗨TT,感谢您的评论。我刚刚添加了一个我尝试过的查询。 – Roeland