Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Trouver le nombre total de minutes en ignorant le chevauchement (convertir la réponse basée sur le curseur en CTE)

La requête suivante recherche les périodes dans les données, selon votre définition. Il utilise d'abord des sous-requêtes corrélées pour déterminer si un enregistrement est le début d'une période (c'est-à-dire qu'il n'y a pas de chevauchement avec des périodes antérieures). Il attribue ensuite le "periodStart" comme le début le plus récent qui est le début d'une période sans chevauchement.

La requête suivante (non testée) adopte cette approche :

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 (Deuxième requête)

Si deux périodes commencent toutes les deux en même temps, cela fonctionne toujours, car les valeurs AvailStart sont les mêmes. En raison des sous-requêtes corrélées, cela peut ne pas fonctionner très bien, même sur des ensembles de données de taille moyenne.

Il existe d'autres méthodes pour aborder cela. Par exemple, si vous aviez SQL Server 2012, vous pourriez utiliser les fonctions de somme cumulative, qui offrent une méthode plus simple.