sql >> Database >  >> RDS >> Sqlserver

Vind totale minuten zonder overlap (converteer op cursor gebaseerd antwoord naar CTE)

De volgende query vindt de punten in de gegevens, volgens uw definitie. Het gebruikt eerst gecorreleerde subquery's om te bepalen of een record het begin is van een periode (dat wil zeggen, geen overlap met eerdere tijdsperioden). Het wijst vervolgens de "periodeStart" toe als de meest recente start die het begin is van een niet-overlappende periode.

De volgende (niet-geteste) query volgt deze benadering:

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 (Tweede zoekopdracht)

Als twee perioden beide tegelijkertijd beginnen, werkt het nog steeds, omdat de AvailStart-waarden hetzelfde zijn. Vanwege de gecorreleerde subquery's presteert dit mogelijk niet erg goed, zelfs niet op middelgrote datasets.

Er zijn andere methoden om dit te benaderen. Als u bijvoorbeeld SQL Server 2012 had, zou u cumulatieve somfuncties kunnen gebruiken, die een eenvoudigere methode bieden.



  1. Hiërarchische zoekopdracht - Records tellen die bij bovenliggende en onderliggende plaatsen horen

  2. maak een query, krijg resultaten maak een query opnieuw

  3. Hoe kan ik de standaardwaarde van een veld instellen op '0000-00-00 00:00:00'?

  4. Een tabel verwijderen in PostgreSQL zonder een bijbehorende reeks te verwijderen