sql >> Databasteknik >  >> RDS >> Sqlserver

Kan jag använda en SQL Server CTE för att sammanfoga korsande datum?

Slutfö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

Ger nu det begärda resultatet och på riktigt täcker alla möjliga fall, inklusive disjunkta undergrupper och dubbletter. Ta en titt på kommentarerna till testdata i fungerande demo på data.SE .

  • CTE 1
    Hitta de (unika!) tidpunkterna där en ny grupp av överlappande intervall börjar.

  • CTE 2
    Räkna starten av en ny grupp upp till (och inklusive) varje enskilt intervall, och bildar därmed ett unikt gruppnummer per användare.

  • Final SELECT
    Slå samman grupperna, ta tidig start och senaste slutet för grupper.

Jag stötte på vissa svårigheter eftersom T-SQL-fönster fungerar max() eller sum() acceptera inte en ORDER BY klausul i en i ett fönster. De kan bara beräkna ett värde per partition, vilket gör det omöjligt att beräkna en löpande summa/antal per partition. Skulle fungera i PostgreSQL eller Oracle (men inte i MySQL, naturligtvis - det har varken fönsterfunktioner eller CTEs).

Den slutliga lösningen använder en extra CTE och bör vara lika snabb.



  1. Hur man ställer in en fjärransluten MySQL-anslutning

  2. MySQL JSON-lagring vs två tabeller

  3. Enkel If Else-sats i sql

  4. Specialtecken i PHP/MySQL