sql >> Database >  >> RDS >> Sqlserver

Kan ik een SQL Server CTE gebruiken om elkaar kruisende datums samen te voegen?

Volledig herschrijven:

;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

Produceert nu het gevraagde resultaat en echt omvat alle mogelijke gevallen, inclusief gescheiden subgroepen en duplicaten. Bekijk de opmerkingen bij de testgegevens in de werkende demo op data.SE .

  • CTE 1
    Zoek de (unieke!) tijdstippen waarop een nieuwe groep overlappende intervallen begint.

  • CTE 2
    Tel de start van een nieuwe groep tot (en inclusief) elke individuele interval, en vormt zo een uniek groepsnummer per gebruiker.

  • Finale SELECT
    Voeg de groepen samen, neem vroege start en laatste einde voor groepen.

Ik had wat problemen, omdat T-SQL-vensterfuncties max() of sum() accepteer geen ORDER BY clausule in a in een venster. Ze kunnen slechts één waarde per partitie berekenen, waardoor het onmogelijk is om een ​​lopende som / telling per partitie te berekenen. Zou werken in PostgreSQL of Oracle (maar niet in MySQL natuurlijk - het heeft geen vensterfuncties of CTE's).

De uiteindelijke oplossing gebruikt één extra CTE en zou net zo snel moeten zijn.



  1. stel sqlite db correct in op Android

  2. 7 strategieën om het meeste uit uw vergaderingen te halen

  3. Kan worden voorkomen dat Django lange tabelnamen afkapt?

  4. Entity Framework + MySQL-klasse genereren