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

OracleSQL-順次値の範囲を特定する

    これは、タビビトサンと呼ばれる手法で簡単に行うことができます。

    この手法では、各グループの行の位置を行のセット全体と比較して、同じグループの行が隣り合っているかどうかを判断します。

    たとえば、サンプルデータでは、次のようになります。

    WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                        SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
    -- end of mimicking your table with data in it. See the SQL below:
    SELECT ID,
           NAME,
           department,
           row_number() OVER (ORDER BY ID) overall_rn,
           row_number() OVER (PARTITION BY department ORDER BY ID) department_rn,
           row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
    FROM   your_table;
    
            ID NAME    DEPARTMENT OVERALL_RN DEPARTMENT_RN        GRP
    ---------- ------- ---------- ---------- ------------- ----------
             1 Michael Marketing           1             1          0
             2 Alex    Marketing           2             2          0
             3 Tom     Marketing           3             3          0
             4 John    Sales               4             1          3
             5 Brad    Marketing           5             4          1
             6 Leo     Marketing           6             5          1
             7 Kevin   Production          7             1          6
    

    ここでは、データセット全体のすべての行に、IDの昇順(overall_rn)の行番号を付けました。 列)、各部門の行に行番号(department_rn)を付けました 列)、IDの昇順。

    これで、一方を他方から減算できます(grp 列)。

    grp列の数値は、隣接するdeparment行で同じままですが、ギャップがあるたびに変化することに注意してください。

    例えば。マーケティング部門の場合、行1〜3は隣り合っており、grp =0ですが、4番目のマーケティング行は実際には結果セット全体の5行目にあるため、grp番号が異なります。 5番目のマーケティング行はセット全体の6行目にあるため、4番目のマーケティング行と同じgrp番号を持っているため、互いに隣接していることがわかります。

    そのgrp情報を取得したら、部門と新しいgrp列の両方で集計クエリグループを作成し、minとmaxを使用して開始IDと終了IDを見つけるだけです。

    WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                        SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
    -- end of mimicking your table with data in it. See the SQL below:
    SELECT department,
           MIN(ID) start_id,
           MAX(ID) end_id
    FROM   (SELECT ID,
                   NAME,
                   department,
                   row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
            FROM   your_table)
    GROUP BY department, grp;
    
    DEPARTMENT   START_ID     END_ID
    ---------- ---------- ----------
    Marketing           1          3
    Marketing           5          6
    Sales               4          4
    Production          7          7
    

    注:id列のギャップは重要ではないと仮定しました(つまり、id =6の行がなかった場合(つまり、LeoとKevinのIDはそれぞれ7と8でした)、LeoとBradは同じように表示されますグループ、開始ID=5および終了ID=7。

    id列のギャップが新しいグループを示していると見なされる場合は、idを使用して行のセット全体にラベルを付けることができます(つまり、overall_rnを計算する必要はなく、代わりにid列を使用するだけです)。

    つまり、クエリは次のようになります。

    WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                        SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 7 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                        SELECT 8 ID, 'Kevin' NAME, 'Production' department FROM dual)
    -- end of mimicking your table with data in it. See the SQL below:
    SELECT department,
           MIN(ID) start_id,
           MAX(ID) end_id
    FROM   (SELECT ID,
                   NAME,
                   department,
                   ID - row_number() OVER (PARTITION BY department ORDER BY ID) grp
            FROM   your_table)
    GROUP BY department, grp;
    
    DEPARTMENT   START_ID     END_ID
    ---------- ---------- ----------
    Marketing           1          3
    Sales               4          4
    Marketing           5          5
    Marketing           7          7
    Production          8          8
    


    1. データを別のテーブルにコピーする

    2. PostgreSQLでのAcosh()のしくみ

    3. Node.jsを介してPostgresに接続する方法

    4. SQLServerデータベースのすべてのテーブルのID列に主キー制約を追加する方法-SQLServer/TSQLチュートリアルパート63