假设我有几行(按日期排序),其中一列包含以下数据:
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。但是,如何解决其他数据库问题也很有趣。
由于
答案 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
答案 1 :(得分:0)
这是SQL Server 2008 R2的部分解决方案,但应在其他数据库上实施。 ones
是您的原始表,其中id
键字段反映了数据的顺序(1,2,3等)。 flag
包含1
和0
个条目。它通过计算每行之前出现的包含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