Spróbuj tego:
;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
- Pierwsze CTE uzyskuje różnice przy użyciu
lag
funkcja (dostępna od SQL Server 2012 r.). - Następny CTE oblicza, kiedy różnica przekracza 1 i przypisuje wszystkie rekordy po tym punkcie do „grupy”, aż do znalezienia następnej różnicy <> 1. To jest kluczowy krok w grupowaniu.
- Ostatnim krokiem jest użycie
dense_rank
nad wskaźnikiem obliczonym w poprzednim kroku, aby uzyskać wymagane numery wierszy.
To rozwiązanie ma ograniczenie oznacza to, że nie powiedzie się, jeśli różnice nie są w kolejności rosnącej, tj. jeśli masz dwie dodatkowe wartości w przykładowych danych, takie jak 52 i 53, zaklasyfikuje je do grupy 3 zamiast tworzyć nową grupę.
Aktualizacja :Poniższe podejście może przezwyciężyć powyższe ograniczenie:
;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
Znowu pierwszy krok pozostaje taki sam. Ale w kroku 2 sprawdzamy tylko przejście do innej wartości różnicy między kolejnymi wartościami, zamiast używać funkcji min/max. Ranking następnie wykorzystuje sumę warunkową do przypisania grupy do każdej wartości w oryginalnych danych.
Można to jeszcze bardziej uprościć do:
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