Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Encontrar o total de minutos ignorando a sobreposição (converter a resposta baseada no cursor para CTE)


A consulta a seguir encontra os períodos nos dados, de acordo com sua definição. Ele usa subconsultas correlacionadas primeiro para determinar se um registro é o início de um período (ou seja, sem sobreposição com períodos anteriores). Em seguida, ele atribui o "periodStart" como o início mais recente que é o início de um período sem sobreposição.

A consulta a seguir (não testada) usa essa abordagem:
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 (Segunda Consulta)

Se dois períodos iniciarem ao mesmo tempo, ainda funcionará, porque os valores de AvailStart são os mesmos. Por causa das subconsultas correlacionadas, isso pode não funcionar muito bem em conjuntos de dados de tamanho médio.

Existem outros métodos para abordar isso. Por exemplo, se você tiver o SQL Server 2012, poderá usar funções de soma cumulativa, que oferecem um método mais simples.