x
create table sample(id integer, name varchar(100), timeint time);
insert into sample values(1, 'aaa', '00:00:01');
insert into sample values(1, 'aaa', '00:00:01');
insert into sample values(1, 'aaa', '00:00:02');
insert into sample values(1, 'aaa', '00:00:03');
insert into sample values(1, 'aaa', '00:00:04');
insert into sample values(2, 'bbb', '00:00:01');
insert into sample values(2,'bbb', '00:00:02');
insert into sample values(2, 'bbb', '00:00:03');
select id,name,timeint,count(timeint) from sample
group by id,name,timeint;
——output will be like—-
1 aaa 00:00:01 2
1 aaa 00:00:02 1
1 aaa 00:00:03 1
1 aaa 00:00:04 1
2 bbb 00:00:01 1
2 bbb 00:00:02 1
2 bbb 00:00:03 1
So the above output should be regrouped in such a manner that for same id and name , timeint with 1 sec tolerance should be considered as same
______ expected output _________________
1 aaa 00:00:01 3
1 aaa 00:00:03 2
2 bbb 00:00:01 2
2 bbb 00:00:03 1
Advertisement
Answer
The general solution to your problem requires a recursive CTE. If all times are accurate to one second and you only want two seconds, there might be a way around that.
However, this solution uses a recursive CTE:
with recursive s as (
select s.id, s.name, s.timeint, count(*) as cnt,
row_number() over (partition by id order by timeint) as seqnum
from sample s
group by s.id, s.name, s.timeint
),
cte as (
select id, timeint, name, seqnum, timeint as start_timeint, cnt
from s
where seqnum = 1
union all
select s.id, s.timeint, s.name, s.seqnum,
(case when s.timeint <= cte.start_timeint + interval '1 second'
then cte.start_timeint else s.timeint
end),
s.cnt
from cte join
s
on s.id = cte.id and s.seqnum = cte.seqnum + 1
)
select id, name, start_timeint, sum(cnt)
from cte
group by id, name, start_timeint
order by id, start_timeint;
Here is a db<>fiddle.