Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Appiattimento di intervalli di tempo che si intersecano

Ecco una soluzione solo SQL. Ho usato DATETIME per le colonne. Memorizzare l'ora separatamente è un errore secondo me, poiché avrai problemi quando l'ora supera la mezzanotte. Puoi modificarlo per gestire quella situazione, se necessario. La soluzione presuppone inoltre che gli orari di inizio e fine NON siano NULL. Anche in questo caso, puoi regolare secondo necessità se non è così.

L'essenza generale della soluzione è ottenere tutti gli orari di inizio che non si sovrappongono a nessun altro intervallo, ottenere tutti gli orari di fine che non si sovrappongono ad alcun intervallo, quindi abbinare i due insieme.

I risultati corrispondono ai risultati attesi tranne in un caso, in cui il controllo manuale sembra che tu abbia un errore nell'output previsto. Il 6 dovrebbe esserci un intervallo che termina alle 06-06-2009 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