sql >> Databáze >  >> RDS >> Sqlserver

Najít celkový počet minut při ignorování překrytí (převést odpověď na základě kurzoru na CTE)

Následující dotaz najde období v datech podle vaší definice. Nejprve používá korelované poddotazy k určení, zda záznam je začátkem období (to znamená, že se nepřekrývá s dřívějšími časovými obdobími). Poté přiřadí „periodStart“ jako nejnovější začátek, který je začátkem nepřekrývajícího se období.

Následující (netestovaný) dotaz používá tento přístup:

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 (Druhý dotaz)

Pokud dvě období začínají současně, pak to stále funguje, protože hodnoty AvailStart jsou stejné. Kvůli korelovaným poddotazům to nemusí fungovat dobře ani na středně velkých souborech dat.

Existují i ​​jiné metody, jak k tomu přistupovat. Pokud byste například měli SQL Server 2012, mohli byste používat funkce kumulativního součtu, které nabízejí jednodušší metodu.



  1. Poskytovatel Oracle pro Oledb chybí ve VS 2015 Shell

  2. Jak rozšířit Joomla! do mého vlastního souboru PHP

  3. Rekurzivní kategorie s jediným dotazem?

  4. Rekurzivní dotaz na závislosti tabulek se neopakuje tolik, jak bych chtěl