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

OracleのTop-Nクエリとページネーション

    Top-Nクエリとページ付けは、Webベースのアプリケーションで一般的です。ユーザーは一連の基準を入力します。これによりクエリが実行され、[前へ]ボタンと[次へ]ボタンをクリックして結果セットをページングできます。このページング機能を実現するには、アプリケーションがデータベースクエリから特定の行セットを取得できる必要があります。

    OracleのトップNクエリとOracleクエリのページネーションを実現するためのOracleのさまざまな方法を見てみましょう

    12c以前

    (1)ROWNUM句の使用

    ROWNUMとは
    これは、クエリで使用できる疑似列(実際の列ではありません)です。 ROWNUMには、番号1、2、3、4、…Nが割り当てられます。ここで、Nは、ROWNUMが使用されるセット内の行数です。 ROWNUM値は、行に永続的に割り当てられません。

    上位5つの値を取得する方法は次のとおりです

    SELECT *
    FROM (SELECT *
    FROM dept
    ORDER BY sales DESC)
    WHERE ROWNUM <= 5;

    このバージョンでは、売上高の降順で部門を並べ替えてから、検出した最初の5つのレコード(上位5つのレコード)を返します。これに行きなさい。

    SELECT a.*
    FROM (SELECT ROWNUM rn, b.*
    FROM ( SELECT *
    FROM dept
    ORDER BY sales dsc) b  where rn <=10) a
    WHERE a.rn >= 5

    一般的な構文は次のようになります

    select *
    from
    ( select rownum rnum, a.*
    from (your_query) a
    where rownum <= M )
    where rnum >= N;

    (2)ROW_NUMBER()oracle分析関数の使用:ROWNUM疑似列と同様に動作しますが、より柔軟性があり、より多くの機能を備えています

    上位5つの値を取得する方法は次のとおりです

    SELECT *
    FROM (SELECT d.*,row_number() over (ORDER BY d.sales DSC) rn
    FROM dept d
    )
    WHERE rn <= 5;

    これがページネーションのクエリです

    SELECT * FROM (
    SELECT
    d.*,
    row_number() over (ORDER BY d.sales DSC) rn
    FROM dept d) WHERE rn BETWEEN 0 AND 5 ORDER BY rn;

    上記の上位N個のクエリは、上位n個のクエリを使用するときに2つのものがその場で結びついている場合に、異なるレコードを返します


    (3)RANK()とDENSE_RANK()の使用:これらは、上記の問題を取り除くために使用できる分析関数です
    ランクを使用して上位5つの値を取得する方法は次のとおりです

    SELECT *
    FROM (SELECT d.*,rank() over (ORDER BY d.sales DSC) rn
    FROM dept d
    )
    WHERE rn <= 5;

    これがdense_rankを使用して上位5つの値を取得する方法です

    SELECT *
    FROM (SELECT d.*,dense_rank() over (ORDER BY d.sales DSC) rn
    FROM dept d
    )
    WHERE rn <= 5;

    12cを使用

    トップN機能

    Oracle Database 12cには、ANSI標準のFETCH FIRST / NEXT句とOFFSET句(まとめて行制限句と呼ばれる)のサポートが含まれています。この句を使用すると、結果セットから最初のNレコードを簡単に取得できます。または、レコードセットをスキップした後、最初のNレコードを取得できるため、結果セットを簡単にページごとに移動できます。

    Top-Nクエリを使用すると、順序セットから上位または下位のN行を取得できます。 2つのTop-Nクエリを組み合わせると、順序付けられたセットをページングすることができます

    例:

    SELECT value
    FROM mytable
    ORDER BY value DESC
    FETCH FIRST 10 ROWS ONLY;  
    
    select * from my_test order by name fetch first 3 rows only;

    上記のクエリのオプティマイザプランを見ると、それを実行するためにまだrow_number()を使用しています

    オフセット構文を使用すると、この機能でもページネーションが発生する可能性があります

    –オフセット10行は、最初の10行のみをフェッチします

    select * from my_test order by id
    offset 10 rows fetch next 10 rows only;

    –オフセット10行は、最初の0.1パーセント行のみをフェッチします

    select * from my_test order by id offset 10 rows first 0.1 percent rows only;

    –オフセット10行は、タイで最初の3行をフェッチします。これは、タイのある一番上の行もすべて結果に含まれることを意味します

    select * from my_test order by name fetch first 3 rows with ties;

    上記のクエリのオプティマイザプランを確認すると、オプティマイザが上記のPre 12cの場合に示されているようにrank()関数を使用していることがわかります

    制限
    (1)FOR UPDATEを含むSELECTステートメントがある場合、それを使用することはできません。
    (2)SELECTステートメントはシーケンスのCURRVALまたはNEXTVALを使用できません
    (3)Ifマテリアライズドビューのクエリにこの句が含まれている場合、そのマテリアライズドビューの増分更新を実行することはできません

    オラクルのトップNクエリとオラクルクエリのページネーションに関する記事が気に入っていただければ幸いです。フィードバックを提供してください

    また読む
    Oracleのリード関数
    OracleのRANK関数
    https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqljoffsetfetch.html


    1. SQLのカーソルとは何ですか?それを実装する方法は?

    2. AlwaysOn可用性グループの構成-パート2

    3. ローリング期間の累計を作成する方法

    4. MySQL LIMIT、OFFSETを使用したページネーション