简体   繁体   中英

Merge consecutive time record in SQL server 2008

Say I have data like this, timeslots is basically time with 30 mins apart. Note there is a gap in 2021-12-24 between 15:30 and 16:30.

calender_date timeslot timeslot_end
2021-12-24 14:00:00 14:30:00
2021-12-24 14:30:00 15:00:00
2021-12-24 15:00:00 15:30:00
2021-12-24 16:30:00 17:00:00
2021-12-24 17:00:00 17:30:00
2021-12-24 17:30:00 18:00:00
2021-12-30 09:00:00 09:30:00
2021-12-30 09:30:00 10:00:00

I want to merge rows where timeslot_end = next row's timeslot and in the same day, so data would look like this.

calender_date timeslot timeslot_end
2021-12-24 14:00:00 15:30:00
2021-12-24 16:30:00 18:00:00
2021-12-30 9:00:00 10:00:00

I have try row numbering with self join,

WITH cte AS
(
    SELECT       
                calender_date 
                ,timeslot
                ,timeslot_end
                ,ROW_NUMBER()OVER(ORDER BY [timeslot])rn
    
    FROM @tmp_leave tl
)

SELECT  
        MIN(a.timeslot) OVER(PARTITION BY a.calender_date, DATEDIFF(minute,a.timeslot_end, 
            ISNULL(b.timeslot, a.timeslot_end))) AS 'StartTime',
        MAX(a.timeslot_end ) OVER(PARTITION BY a.calender_date, 
            DATEDIFF(minute,a.timeslot_end, ISNULL(b.timeslot, a.timeslot_end))) AS 'EndTime'
        
FROM cte a 
LEFT JOIN cte b
       ON a.rn + 1 = b.rn AND a.timeslot_end = b.timeslot
ORDER BY calender_date

But the result isn't quite right, it ignored the gap in 2021-12-24 and return below.

calender_date timeslot timeslot_end
2021-12-24 14:00:00 18:00:00
2021-12-30 9:00:00 10:00:00

I have been searching and trying to solve it for a while now, please help, any help is very very appreciated!!

This is a gaps and islands problem. We can approach this by creating pseudo groups for each island of continuous dates/times.

WITH cte AS (
    SELECT *, LAG(timeslot_end) OVER
                  (ORDER BY calendar_date, timeslot) timeslot_end_lag
    FROM yourTable
),
cte2 AS (
    SELECT *, COUNT(CASE WHEN timeslot_end_lag <> timeslot THEN 1 END)
                  OVER (ORDER BY calendar_date, timeslot) AS grp
    FROM cte
)

SELECT calendar_date,
       MIN(timeslot) AS timeslot,
       MAX(timeslot_end) AS timeslot_end
FROM cte2
GROUP BY calendar_date, grp
ORDER BY calendar_date;

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM