これを試してください:
;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
- 最初の CTE は
lag
を使用して違いを取得します 関数 (SQL Server 2012 以降で使用可能)。 - 次の CTE は、差が 1 を超えると計算し、次の差 <> 1 が見つかるまで、その時点以降のすべてのレコードを「グループ」に割り当てます。これがグループ化の重要なステップです。
- 最後のステップは、
dense_rank
を使用することです 必要に応じて行番号を取得するために、前のステップで計算されたインジケーターを上書きします。
このソリューションには制限があります 差が昇順でない場合、つまりサンプル データに 52 と 53 などの値が 2 つ以上ある場合、新しいグループを作成する代わりにそれらをグループ 3 に分類するという点で失敗します。
更新 :以下のアプローチにより、上記の制限を克服できます:
;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
ここでも、最初のステップは同じままです。ただし、ステップ 2 では、最小/最大関数を使用する代わりに、連続する値の差の異なる値への遷移のみを確認します。次に、ランキングは条件付き合計を使用して、元のデータの各値にグループを割り当てます。
これはさらに次のように単純化できます:
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