SQL - 对有序数字序列

时间:2016-05-15 20:29:35

标签: sql postgresql

假设我有几行(按日期排序),其中一列包含以下数据:

1
1
1
0
0
1
0
1
1
1

等。 如何在达到下一个0之前选择1的计数,然后重置计数器。例如,查询应返回以下数据:

1 
1 
1 3
0  
0  
1 1
0 
1 
1 
1 3

实际上,我不需要实际数据,如果查询只返回聚合/计数,我没问题。为了便于理解,我只是包含了第一列。 我正在运行PostgreSQL 9.5。但是,如何解决其他数据库问题也很有趣。

由于

2 个答案:

答案 0 :(得分:1)

在这个SQL中,我假设列c1是日期的序列

drop table if exists t5;
create table t5 (c1 int primary key, c2 int);

insert into t5 values (1, 1);
insert into t5 values (2, 1);
insert into t5 values (3, 1);
insert into t5 values (4, 0);
insert into t5 values (5, 0);
insert into t5 values (6, 1);
insert into t5 values (7, 0);
insert into t5 values (8, 1);
insert into t5 values (9, 1);
insert into t5 values (10, 1);

select grp, max(cnt) from (
    with recursive t(id, cnt, grp) as (
        select c1, c2, 1
        from t5
        where c1 = 1
        union all
        select c1, 
               -- if next is 1 increment existing count else set it to zero
               case when b.c2 = 1 then cnt+1 else 0 end, 
               -- if 0 change group else retain group [0 to 1 will retain group] 
               -- as long as '1' to '0' changes the group we are good
               case when b.c2 = 1 then grp else grp+1 end
        from t5 b, t
        where b.c1 = id + 1
    ) 
    select * from t
) t  group by grp having max(cnt) > 0 order by grp

<强>输出 enter image description here

答案 1 :(得分:0)

这是SQL Server 2008 R2的部分解决方案,但应在其他数据库上实施。 ones是您的原始表,其中id键字段反映了数据的顺序(1,2,3等)。 flag包含10个条目。它通过计算每行之前出现的包含flag = 0的行来对数据进行分组。每次运行1都会计算出之前出现的越来越多的零,因此您可以使用它来唯一标识1的每次运行。 它不会提供运行计数,但会为每次1次运行提供摘要计数。

create table ones_summary ( PreviousZeros int )

insert ones_summary
select ( select count(*) as N from ones t2 where t2.id < t1.id and t2.flag = 0 ) as PreviousZeros
 from ones t1 
 where t1.flag = 1

select PreviousZeros, count(*) 
from ones_summary
group by PreviousZeros