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;
假设我有以下记录:
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;