Flattening intersecting timespans

前端 未结 7 1423
温柔的废话
温柔的废话 2020-12-14 19:56

I have lots of data with start and stop times for a given ID and I need to flatten all intersecting and adjacent timespans into one combined timespan. The sample data posted

7条回答
  •  一生所求
    2020-12-14 20:17

    Here is a SQL only solution. I used DATETIME for the columns. Storing the time separate is a mistake in my opinion, as you will have problems when the times go past midnight. You can adjust this to handle that situation though if you need to. The solution also assumes that the start and end times are NOT NULL. Again, you can adjust as needed if that's not the case.

    The general gist of the solution is to get all of the start times that don't overlap with any other spans, get all of the end times that don't overlap with any spans, then match the two together.

    The results match your expected results except in one case, which checking by hand looks like you have a mistake in your expected output. On the 6th there should be a span that ends at 2009-06-06 10:18:45.000.

    SELECT
         ST.start_time,
         ET.end_time
    FROM
    (
         SELECT
              T1.start_time
         FROM
              dbo.Test_Time_Spans T1
         LEFT OUTER JOIN dbo.Test_Time_Spans T2 ON
              T2.start_time < T1.start_time AND
              T2.end_time >= T1.start_time
         WHERE
              T2.start_time IS NULL
    ) AS ST
    INNER JOIN
    (
         SELECT
              T3.end_time
         FROM
              dbo.Test_Time_Spans T3
         LEFT OUTER JOIN dbo.Test_Time_Spans T4 ON
              T4.end_time > T3.end_time AND
              T4.start_time <= T3.end_time
         WHERE
              T4.start_time IS NULL
    ) AS ET ON
         ET.end_time > ST.start_time
    LEFT OUTER JOIN
    (
         SELECT
              T5.end_time
         FROM
              dbo.Test_Time_Spans T5
         LEFT OUTER JOIN dbo.Test_Time_Spans T6 ON
              T6.end_time > T5.end_time AND
              T6.start_time <= T5.end_time
         WHERE
              T6.start_time IS NULL
    ) AS ET2 ON
         ET2.end_time > ST.start_time AND
         ET2.end_time < ET.end_time
    WHERE
         ET2.end_time IS NULL
    

提交回复
热议问题