La query seguente trova i periodi nei dati, secondo la tua definizione. Utilizza prima le sottoquery correlate per determinare se un record è l'inizio di un periodo (ovvero, nessuna sovrapposizione con periodi di tempo precedenti). Quindi assegna "periodStart" come inizio più recente che è l'inizio di un periodo non sovrapposto.
La seguente query (non testata) utilizza questo approccio:
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 (Seconda richiesta)
Se due periodi iniziano entrambi contemporaneamente, funziona ancora, perché i valori di AvailStart sono gli stessi. A causa delle sottoquery correlate, questo potrebbe non funzionare molto bene anche su set di dati di medie dimensioni.
Ci sono altri metodi per avvicinarsi a questo. Ad esempio, se avessi SQL Server 2012, saresti in grado di utilizzare le funzioni di somma cumulativa, che offrono un metodo più semplice.