Hier ist eine reine SQL-Lösung. Ich habe DATETIME für die Spalten verwendet. Die separate Speicherung der Uhrzeit ist meiner Meinung nach ein Fehler, da Sie Probleme haben werden, wenn die Uhrzeiten nach Mitternacht gehen. Sie können dies jedoch anpassen, um mit dieser Situation umzugehen, wenn dies erforderlich ist. Die Lösung geht außerdem davon aus, dass die Start- und Endzeiten NICHT NULL sind. Auch hier können Sie nach Bedarf anpassen, wenn dies nicht der Fall ist.
Der allgemeine Kern der Lösung besteht darin, alle Startzeiten abzurufen, die sich nicht mit anderen Spannen überschneiden, alle Endzeiten abzurufen, die sich nicht mit anderen Spannen überschneiden, und dann die beiden miteinander abzugleichen.
Die Ergebnisse stimmen mit Ihren erwarteten Ergebnissen überein, außer in einem Fall, bei dem die Überprüfung von Hand so aussieht, als hätten Sie einen Fehler in Ihrer erwarteten Ausgabe. Am 6. sollte es eine Spanne geben, die um 2009-06-06 10:18:45.000 endet.
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