Poniższe zapytanie znajduje kropki w danych, zgodnie z twoją definicją. Najpierw używa skorelowanych podzapytań, aby określić, czy rekord jest początkiem okresu (to znaczy, czy nie nakłada się na wcześniejsze okresy). Następnie przypisuje "periodStart" jako najnowszy początek, który jest początkiem nienakładającego się okresu.
Poniższe (nieprzetestowane) zapytanie przyjmuje takie podejście:
with TimeWithOverlap as (
select t.*,
(case when exists (select * from dbo.Available tbefore where t.availStart > tbefore.availStart and tbefore.availEnd >= t.availStart)
then 0
else 1
end) as IsPeriodStart
from dbo.Available t
),
TimeWithPeriodStart as (
select two.*,
(select MAX(two1.AvailStart) from TimeWithOverlap two1 where IsPeriodStart = 1 and two1.AvailStart <= two.AvailStart
) as periodStart
from TimeWithOverlap two
)
select periodStart, MAX(AvailEnd) as periodEnd
from TimeWithPeriodStart twps
group by periodStart;
http://sqlfiddle.com/#!6/3483c/20 (Drugie zapytanie)
Jeśli dwa okresy zaczynają się w tym samym czasie, to nadal działa, ponieważ wartości AvailStart są takie same. Z powodu skorelowanych podzapytań może to nie działać zbyt dobrze nawet w przypadku średnich zestawów danych.
Istnieją inne metody podejścia do tego. Na przykład, jeśli masz SQL Server 2012, możesz użyć funkcji sumy zbiorczej, które oferują prostszą metodę.