You can create an aggregate with 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 correct order to get the following daily range for the last received_from:
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 the 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"] │ └────┴─────────┴────────────────────────┴─────────────────────────────────────────────────────┘
Request 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 │ └────────────────────────┴────────┘
Emre Hasegeli
source share