I do not have access to PostgreSQL, but hopefully this works ...
WITH grouped_data AS ( SELECT ROW_NUMBER() OVER (PARTITION BY myuser ORDER BY day) - (day - start_date) AS user_group_id, myuser, day FROM myTable WHERE day >= start_date - 3 AND day <= end_date ) , sequenced_data AS ( SELECT ROW_NUMBER() OVER (PARTITION BY myuser, user_group_id ORDER BY day) AS sequence_id, myuser, day FROM grouped_data ) SELECT myuser, day, CASE WHEN sequence_id % 4 = 0 THEN 1 ELSE 0 END as should_be_a_break_day FROM sequenced_data WHERE day >= start_date
Sorry, I didnโt explain the work, I had to jump to the meeting :)
Example with start_date = '2012-01-14' ...
id | myuser | day | ROW_NUMBER() | day - start_date | user_group_id ----+--------+------------+--------------+------------------+--------------- 0 | 200 | 2012-01-12 | 1 | -2 | 1 - -2 = 3 1 | 200 | 2012-01-13 | 2 | -1 | 2 - -1 = 3 2 | 200 | 2012-01-14 | 3 | 0 | 3 - 0 = 3 3 | 200 | 2012-01-15 | 4 | 1 | 4 - 1 = 3 4 | 200 | 2012-01-16 | 5 | 2 | 5 - 2 = 3 ----+--------+------------+--------------+------------------+--------------- 5 | 201 | 2012-01-12 | 1 | -2 | 1 - -2 = 3 6 | 201 | 2012-01-13 | 2 | -1 | 2 - -1 = 3 7 | 201 | 2012-01-14 | 3 | 0 | 3 - -1 = 3 8 | 201 | 2012-01-16 | 4 | 2 | 4 - 2 = 2
Any consecutive dates will have the same user_group_id. Each โspaceโ in days reduces the value of user_group_id by 1 (see Line 8, if the record was for the 17th, a space of 2 days, the identifier would be 1).
Once you have group_id, row_number () can be easily used to tell which day in its sequence. A maximum of 3 days is the same as โEvery 4th day should be a space,โ and โx% 4 = 0โ means every 4th day.
source share