记录结果的连续计数

时间:2016-03-01 02:05:51

标签: sql sql-server tsql row-number gaps-and-islands

我正在处理一个数据结构,其中包含每个人的正面或负面结果列表。

示例数据(id是身份):

id      person  result
1       1       0
2       1       1
3       1       1
4       2       1
5       2       0
6       1       1
7       1       0
8       2       0
9       2       0
10      2       0

有了这个,我想计算每个人consecutive result = 1的最大数量。该样本的结果将是

person  max_count
1       3
2       1

我尝试过像这样使用ROW_NUMBER() OVER (PARTITION BY)

SELECT person, 
ROW_NUMBER() OVER (PARTITION BY person, result ORDER BY id) AS max_count      
FROM TABLE 

但它为我提供accumulative个而非consecutive个。

如何进行连续计数?任何提示都将不胜感激。提前致谢

2 个答案:

答案 0 :(得分:3)

这看起来像经典的gaps-and-islands问题。 在下面的查询中检查每个CTE的中间结果,以了解发生了什么。

示例数据

我在人3中添加了两个阳性结果序列,以便找到最长的序列。

DECLARE @T TABLE (id int, person int, result int);
INSERT INTO @T (id, person, result) VALUES
(1 , 1, 0),
(2 , 1, 1),
(3 , 1, 1),
(4 , 2, 1),
(5 , 2, 0),
(6 , 1, 1),
(7 , 1, 0),
(8 , 2, 0),
(9 , 2, 0),
(10, 2, 0),
(11, 3, 0),
(12, 3, 1),
(13, 3, 1),
(14, 3, 1),
(15, 3, 1),
(16, 3, 0),
(17, 3, 1),
(18, 3, 1),
(19, 3, 0),
(20, 3, 0);

<强>查询

WITH
CTE_RowNumbers
AS
(
    SELECT
        id, person, result
        ,ROW_NUMBER() OVER (PARTITION BY person ORDER BY ID) AS rn1
        ,ROW_NUMBER() OVER (PARTITION BY person, result ORDER BY ID) AS rn2
    FROM @T
)
,CTE_Groups
AS
(
    SELECT
        id, person, result
        ,rn1-rn2 AS GroupNumber
    FROM CTE_RowNumbers
)
,CTE_GroupSizes
AS
(
    SELECT
        person
        ,COUNT(*) AS GroupSize
    FROM CTE_Groups
    WHERE
        result = 1
    GROUP BY
        person
        ,GroupNumber
)
SELECT
    person
    ,MAX(GroupSize) AS max_count
FROM CTE_GroupSizes
GROUP BY person
ORDER BY person;

<强>结果

+--------+-----------+
| person | max_count |
+--------+-----------+
|      1 |         3 |
|      2 |         1 |
|      3 |         4 |
+--------+-----------+

答案 1 :(得分:0)

通过使用Case和SUM,我们可以实现上述结果

DECLARE @T TABLE (id int, person int, result int);
    INSERT INTO @T (id, person, result) VALUES
    (1 , 1, 0),
    (2 , 1, 1),
    (3 , 1, 1),
    (4 , 2, 1),
    (5 , 2, 0),
    (6 , 1, 1),
    (7 , 1, 0),
    (8 , 2, 0),
    (9 , 2, 0),
    (10, 2, 0)
    select 
    person,
    SUM(CASE WHEN RESULT = 1 then 1 else 0 END) 
     from @T
    GROUP BY person