問題:行の単一ページの結果セットを返すストアドプロシージャを作成する必要がありますおよび行の総数。
解決策A:2つのストアドプロシージャを作成します。1つは単一ページの結果セットを返し、もう1つはスカラー(合計行)を返します。 Explain Planでは、最初のsprocのコストは9であり、2番目のsprocのコストは3であると述べています。
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) AS RowNum, ...
) AS PageResult
WHERE RowNum >= @from
AND RowNum < @to
ORDER BY RowNum
SELECT COUNT(*)
FROM ...
解決策B:同じTotalRows
番号を結果セットのevery行に追加して、すべてを単一のsprocに入れます。このソリューションはハック感がありますが、コストは9であり、1つのsprocのみであるため、このソリューションを使用したいと思います。
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
AND RowNum < to
ORDER BY RowNum;
Oracleのページネーションのベストプラクティスはありますか?上記のソリューションのうち、実際に最も使用されているのはどれですか?それらのいずれかが単に間違っていると考えられていますか?私のDBは比較的小さく(10GB未満)います。
Oracle 11gおよび最新のODP.NETとVS2010 SP1およびEntity Framework 4.4を使用しています。 EF 4.4内で動作する最終的なソリューションが必要です。一般にページネーションのためのより良い方法があると思いますが、EFで作業する必要があります。
すでに分析(ROW_NUMBER() OVER ...
)を使用している場合、同じパーティションに別の分析関数を追加すると、クエリに無視できるコストが追加されます。
一方、ページネーションを行う方法は他にもたくさんあり、そのうちの1つはrownum
を使用します。
SELECT *
FROM (SELECT A.*, rownum rn
FROM (SELECT *
FROM your_table
ORDER BY col) A
WHERE rownum <= :Y)
WHERE rn >= :X
順序付け列に適切なインデックスがある場合、この方法は優れています。この場合、2つのクエリ(1つは行の総数、1つは結果)を使用する方が効率的です。
どちらの方法も適切ですが、一般に行数とページネーションセットの両方が必要な場合は、行を1回クエリするだけなので、分析の使用がより効率的です。
これは役立つかもしれません:
SELECT * FROM
( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
WHERE Row_Num BETWEEN 5 and 10;
Oracle 12Cでは、ページネーションにlimit LIMIT
とOFFSET
を使用できます。
例-tab
データ型列DATE
に基づいて、ページネーションを使用して降順でデータをフェッチする必要があるテーブルdt
があるとします。
page_size:=5
select * from tab
order by dt desc
OFFSET nvl(page_no-1,1)*page_size ROWS FETCH NEXT page_size ROWS ONLY;
説明:
page_no = 1 page_size = 5
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY
-最初の5行のみを取得
page_no = 2 page_size = 5
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY
-次の5行をフェッチします
等々。
参照ページ-
https://Oracle-base.com/articles/12c/row-limited-clause-for-top-n-queries-12cr1#paging
私も同様の問題に直面しました。上記のソリューションをすべて試してみましたが、パフォーマンスが向上するものはありませんでした。私は数百万のレコードを含むテーブルを持っています。画面に20ページで表示する必要があります。この問題を解決するために以下を行いました。
この方法は、巨大なテーブルで無条件のページネーションフェッチを行う必要がある場合に効果的です。
SQLコードを整理するきれいな方法は、WITH
ステートメントを使用することです。
縮小版は、結果の合計数および合計ページ数も実装します。
例えば
_WITH SELECTION AS (
SELECT FIELDA, FIELDB, FIELDC FROM TABLE),
NUMBERED AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
SELECTION.*
FROM SELECTION)
SELECT
(SELECT COUNT(*) FROM NUMBERED) TOTAL_ROWS,
NUMBERED.*
FROM NUMBERED
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
_
このコードは、さらに2つのフィールドを持つページ化された結果セットを提供します。
TOTAL_ROWS
_完全なSELECTION
の合計行RN
レコードの行番号SELECTION
をスライスするには、2つのパラメーター_:page_size
_と_:page_number
_が必要です。
選択はすでにROW_NUMBER()
フィールドを実装しています
_WITH SELECTION AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
FIELDA,
FIELDB,
FIELDC
FROM TABLE)
SELECT
:page_number PAGE_NUMBER,
CEIL((SELECT COUNT(*) FROM SELECTION ) / :page_size) TOTAL_PAGES,
:page_size PAGE_SIZE,
(SELECT COUNT(*) FROM SELECTION ) TOTAL_ROWS,
SELECTION.*
FROM SELECTION
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
_
申し訳ありませんが、これはソートで動作します:
SELECT * FROM (SELECT ROWNUM rnum,a.* FROM (SELECT * FROM "tabla" order by "column" asc) a) WHERE rnum BETWEEN "firstrange" AND "lastrange";
これを試して:
select * from ( select * from "table" order by "column" desc ) where ROWNUM > 0 and ROWNUM <= 5;