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