sql >> データベース >  >> RDS >> Sqlserver

SQL Server 2012 の後続の行インデックスの違いに基づいてパーティションを作成します

    これを試してください:

        ;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
    


    1. ミリ秒単位のDateTimeの表現?

    2. PostgreSQL列fooは存在しません。fooは値です。

    3. PostgreSQLで「not-null-string」配列のタイプの列を宣言します

    4. Oracleデータベースとのエンティティフレームワーク接続