33

問題: 行の 1 ページと合計行数の結果セットを返すストアド プロシージャを作成する必要があります。

解決策 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の行に同じ番号を追加して、すべてを 1 つの sproc に入れます。このソリューションはハックのように感じますが、コストが 9 で sproc が 1 つしかないため、このソリューションを使用する傾向があります。

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で動作する必要があります。

4

7 に答える 7

39

If you're already using analytics (ROW_NUMBER() OVER ...) then adding another analytic function on the same partitioning will add a negligible cost to the query.

On the other hand, there are many other ways to do pagination, one of them using rownum:

SELECT * 
  FROM (SELECT A.*, rownum rn
          FROM (SELECT *
                  FROM your_table
                 ORDER BY col) A
         WHERE rownum <= :Y)
 WHERE rn >= :X

This method will be superior if you have an appropriate index on the ordering column. In this case, it might be more efficient to use two queries (one for the total number of rows, one for the result).

Both methods are appropriate but in general if you want both the number of rows and a pagination set then using analytics is more efficient because you only query the rows once.

于 2012-12-06T09:04:38.633 に答える
6

これは役立つかもしれません:

   SELECT * FROM 
     ( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
     WHERE Row_Num BETWEEN 5 and 10;
于 2012-12-06T14:07:01.597 に答える
0

申し訳ありませんが、これはソートで機能します:

SELECT * FROM (SELECT ROWNUM rnum,a.* FROM (SELECT * FROM "tabla" order by "column" asc) a) WHERE rnum BETWEEN "firstrange" AND "lastrange";
于 2014-08-19T17:56:23.327 に答える
0

これを試して:

select * from ( select * from "table" order by "column" desc ) where ROWNUM > 0 and ROWNUM <= 5;
于 2014-08-19T17:46:54.053 に答える