Skip to content
Advertisement

get dates periods

it is necessary to get the date periods. input data:

     login    date_start    date_end    code
    'user1', '2022-02-09', '2022-02-09'  DO
    'user1', '2022-02-10', '2022-02-10'  DO
    'user1', '2022-02-11', '2022-02-11'  DO
    'user1', '2022-03-28', '2022-03-28'  OT
    'user1', '2022-03-29', '2022-03-29'  OT
    'user1', '2022-03-30', '2022-03-30'  OT
    'user1', '2022-03-31', '2022-03-31'  OT
    'user1', '2022-04-01', '2022-04-01'  OT
    'user1', '2022-04-04', '2022-04-04'  DO

expected result:

login  date_start  date_end   
user1  2022-02-09  2022-02-11 
user1  2022-03-28  2022-04-01
user1  2022-04-04  2022-04-04

Advertisement

Answer

This is a gaps and islands problem. One trick we can use here is to create a pseudo-group which tracks to which island of continuous dates each record belongs.

WITH cte AS (
    SELECT *, CASE WHEN LAG(date_start, 1, date_start) OVER
                        (PARTITION BY login ORDER BY date_start) =
                        DATEADD(day, -1, date_start)
                   THEN 0 ELSE 1 END AS cnt
    FROM yourTable
),
cte2 AS (
    SELECT *, SUM(cnt) OVER (PARTITION BY login ORDER BY date_start) AS grp
    FROM cte
)

SELECT login, MIN(date_start) AS date_start, MAX(date_end) AS date_end
FROM cte2
GROUP BY login, grp
ORDER BY MIN(date_start);

Demo

In the first CTE above, the alias cnt gets assigned to a value of 1 whenever the preceding date is not one day earlier than the current date. We can then sum over this column and obtain groups of dates forming a continuous range.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement