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

Kan jeg bruge en SQL Server CTE til at flette krydsende datoer?

Fuldfør omskrivning:

;WITH new_grp AS (
   SELECT r1.UserId, r1.StartTime
   FROM   @requests r1
   WHERE  NOT EXISTS (
          SELECT *
          FROM   @requests r2
          WHERE  r1.UserId = r2.UserId
          AND    r2.StartTime <  r1.StartTime
          AND    r2.EndTime   >= r1.StartTime)
   GROUP  BY r1.UserId, r1.StartTime -- there can be > 1
   ),r AS (
   SELECT r.RequestId, r.UserId, r.StartTime, r.EndTime
         ,count(*) AS grp -- guaranteed to be 1+
   FROM   @requests r
   JOIN   new_grp n ON n.UserId = r.UserId AND n.StartTime <= r.StartTime
   GROUP  BY r.RequestId, r.UserId, r.StartTime, r.EndTime
   )
SELECT min(RequestId) AS RequestId
      ,UserId
      ,min(StartTime) AS StartTime
      ,max(EndTime)   AS EndTime
FROM   r
GROUP  BY UserId, grp
ORDER  BY UserId, grp

Producerer nu det ønskede resultat og virkelig dækker alle mulige tilfælde, inklusive adskilte undergrupper og dubletter. Se kommentarerne til testdataene i fungerende demo på data.SE .

  • CTE 1
    Find de (unikke!) tidspunkter, hvor en ny gruppe af overlappende intervaller starter.

  • CTE 2
    Tæl starten af ​​en ny gruppe op til (og inklusive) hvert enkelt interval og danner derved et unikt gruppenummer pr. bruger.

  • Endelig VALG
    Flet grupperne sammen, tag tidlig start og sidste slutning for grupper.

Jeg stod over for nogle vanskeligheder, fordi T-SQL-vinduets funktioner max() eller sum() accepter ikke en ORDER BY klausul i a i et vindue. De kan kun beregne én værdi pr. partition, hvilket gør det umuligt at beregne en løbende sum/antal pr. partition. Ville fungere i PostgreSQL eller Oracle (men ikke i MySQL, selvfølgelig - det har hverken vinduesfunktioner eller CTE'er).

Den endelige løsning bruger en ekstra CTE og bør være lige så hurtig.



  1. Hvordan kører man mysql-kommandoer fra terminal på en MAMP-installation?

  2. mysql - INDSÆT datointerval i datokolonner, HVIS datoer ikke overlapper med eksisterende

  3. Hvad er der galt med denne oprette tabel-erklæring?

  4. Sådan får du den aktuelle tid i PostgreSQL