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

Trova i minuti totali ignorando la sovrapposizione (converti la risposta basata sul cursore a CTE)

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.