Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Erstellen Sie eine Partition basierend auf der Differenz zwischen aufeinander folgenden Zeilenindizes in SQL Server 2012

Versuchen Sie Folgendes:

    ;with cte as
    (select *, 
     coalesce(row_index - (lag(row_index) over (order by event)),1) diff
     from tbl
    ),

    cte2 as
    (select *, 
     (select max(diff) 
      from cte c 
      where c.row_index <= d.row_index
      ) minri
     from cte d
     )

    select event, row_index, minri, 
    dense_rank() over (order by minri) rn 
    from cte2
  • Der erste CTE ruft die Unterschiede mit dem lag ab Funktion (verfügbar ab SQL Server 2012).
  • Der nächste CTE berechnet, wann die Differenz 1 übersteigt und ordnet alle Datensätze danach einer 'Gruppe' zu, bis die nächste Differenz <> 1 gefunden wird. Dies ist der entscheidende Schritt beim Gruppieren.
  • Der letzte Schritt ist die Verwendung von dense_rank über den im vorherigen Schritt berechneten Indikator, um die erforderlichen Zeilennummern zu erhalten.

Diese Lösung hat eine Einschränkung darin, dass es fehlschlägt, wenn die Unterschiede nicht in aufsteigender Reihenfolge sind, d. h. wenn Sie zwei weitere Werte in den Beispieldaten wie 52 und 53 haben, werden sie in Gruppe 3 klassifiziert, anstatt eine neue Gruppe zu erstellen.

Demo

Aktualisieren :Der folgende Ansatz kann die obige Einschränkung überwinden:

    ;with cte as
    (select *, 
     coalesce(row_index - (lag(row_index) over (order by event)),1) diff
     from tbl)
    ,cte2 as
    (select *,
     diff - coalesce(diff - (lag(diff) over (order by event)),0) tmp
     from cte d)

     select event,row_index, 
     1 + sum(case when tmp >= diff then 0 else 1 end) over (order by event) risum
     from cte2

Auch hier bleibt der erste Schritt gleich. Aber in Schritt 2 prüfen wir nur den Übergang zu einem anderen Wert der Differenz zwischen aufeinanderfolgenden Werten, anstatt eine Min/Max-Funktion zu verwenden. Das Ranking verwendet dann eine bedingte Summe, um jedem Wert in den Originaldaten eine Gruppe zuzuweisen.

Demo

Dies kann weiter vereinfacht werden zu:

select event, row_index, 
sum(case when diff <= 1 then 0 else 1 end) over (order by event) as rb
from
(select *, 
 row_index - (lag(row_index) over (order by event)) diff
 from tbl
) s