You can create an aggregate with the range types:
Create function sfunc (tstzrange, timestamptz)
returns tstzrange
language sql strict as $$
select case when $2 - upper($1) <= '1 day'::interval
then tstzrange(lower($1), $2, '[]')
else tstzrange($2, $2, '[]') end
$$;
Create aggregate consecutive (timestamptz) (
sfunc = sfunc,
stype = tstzrange,
initcond = '[,]'
);
Use the aggregate with the right order the get the consecutive day range for the last arrived_at:
Select user_id, consecutive(arrived_at order by arrived_at)
from work
group by user_id;
┌─────────┬─────────────────────────────────────────────────────┐
│ user_id │ consecutive │
├─────────┼─────────────────────────────────────────────────────┤
│ 1 │ ["2011-01-03 00:00:00+02","2011-01-05 00:00:00+02"] │
│ 2 │ ["2011-01-06 00:00:00+02","2011-01-06 00:00:00+02"] │
└─────────┴─────────────────────────────────────────────────────┘
Use the aggregate in a window function:
Select *,
consecutive(arrived_at)
over (partition by user_id order by arrived_at)
from work;
┌────┬─────────┬────────────────────────┬─────────────────────────────────────────────────────┐
│ id │ user_id │ arrived_at │ consecutive │
├────┼─────────┼────────────────────────┼─────────────────────────────────────────────────────┤
│ 1 │ 1 │ 2011-01-03 00:00:00+02 │ ["2011-01-03 00:00:00+02","2011-01-03 00:00:00+02"] │
│ 2 │ 1 │ 2011-01-04 00:00:00+02 │ ["2011-01-03 00:00:00+02","2011-01-04 00:00:00+02"] │
│ 3 │ 1 │ 2011-01-05 00:00:00+02 │ ["2011-01-03 00:00:00+02","2011-01-05 00:00:00+02"] │
│ 4 │ 2 │ 2011-01-06 00:00:00+02 │ ["2011-01-06 00:00:00+02","2011-01-06 00:00:00+02"] │
└────┴─────────┴────────────────────────┴─────────────────────────────────────────────────────┘
Query the results to find what you need:
With work_detail as (select *,
consecutive(arrived_at)
over (partition by user_id order by arrived_at)
from work)
select arrived_at, upper(consecutive) - lower(consecutive) as days
from work_detail
where user_id = 1 and upper(consecutive) != lower(consecutive)
order by arrived_at desc
limit 1;
┌────────────────────────┬────────┐
│ arrived_at │ days │
├────────────────────────┼────────┤
│ 2011-01-05 00:00:00+02 │ 2 days │
└────────────────────────┴────────┘