web-dev-qa-db-ja.com

ROWNUMはページネーションクエリでどのように機能しますか?

そこで、OracleDBの行の範囲を選択したいと思います。テーブルに数百万の行があり、結果をユーザーにページ分割したいので、これを行う必要があります(クライアント側でこれを行う別の方法を知っている場合は、重要な場合はJavaFXを使用していますが、そうではありませんすべてのデータをネットワーク経由で送信して、クライアント側でページ付けすることをお勧めします)。

したがって、この投稿を読んだ後: SQL ROWNUM特定の範囲の間の行を返す方法 、次のクエリがあります:

_Select * From (Select t.*, rownum r from PERSON t) Where r > 100 and r < 110;
_

_100_と_110_は単なる例です。アプリケーションでは、下限を要求し、サイズ10_000を追加して、次の10_000行をフェッチします。

これで、rownum列が結果に表示され、表示したくありません。私はSQLの経験があまりないので、ここに私の質問があります。

  1. なぜ(SOで検索するまでこれが最初の試みでした)_Select * From Person Where rownum > 100 and rownum < 110;_は0行を返しますか?
  2. _Select ... FROM ... WHERE rownum BETWEEN lowerBound AND upperBound_のような簡単な方法がないのはなぜですか?

  3. 結果の値のr列を削除するにはどうすればよいですか?そこから SQLはSELECT * [columnAを除く] FROM tableAを使用して列を除外しますか? ビューまたは一時テーブルを作成する必要があるようですが、クエリを検討する別の方法はありますか?

  4. 正しいページ付けが保証されていますか? この記事 セクション「Paginationwith ROWNUM」を読みました。一貫したページ付けを取得するには、値を一意の順序で並べ替える必要があると書かれています(したがって、rownumで並べ替えても問題ないと思います。確認できます)。 FIRST_ROWS(N)を使用する目的を無効にしませんか?

あまり多くないことを願っています。別々の質問に分割することもできますが、密接に関連しているため、それらを折りたたむことは適切だと思います。

ありがとう:)

9
user2336315

4つの質問があり、すべて[〜#〜] rownum [〜#〜]の使用法と機能を中心に展開しています。それぞれの質問に一つずつ答えていきます。

理由(SOで検索するまではこれが最初の試みでした)Select * From Person Where rownum> 100 and rownum <110; 0行を返しますか?

ROWNUMとページネーションに関するThomasKyteによる素晴らしい説明 ここ

[〜#〜] rownum [〜#〜]値は、行の述語フェーズを通過した後に行に割り当てられます。クエリ。ただし、クエリが並べ替えまたは集計を行う前。また、ROWNUM値は、割り当てられた後にのみインクリメントされます。そのため、次のクエリは行を返しません。

select * 
  from t 
 where ROWNUM > 1;

ROWNUM> 1は最初の行には当てはまらないため、ROWNUMは2に進みません。したがって、ROWNUM値が1より大きくなることはありません。

Select ... FROM ... WHERE rownum BETWEEN lowerBoundとupperBoundのような簡単な方法がないのはなぜですか?

はいあります。 Oracle 12c以降、新しいTop-n行制限機能を使用できます。 ここで私の答えを参照してください

たとえば、次のクエリは、4番目に高いから7番目に高い給与までの従業員を昇順で返します。

SQL> SELECT empno, sal
  2  FROM   emp
  3  ORDER BY sal
  4  OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

     EMPNO        SAL
---------- ----------
      7654       1250
      7934       1300
      7844       1500
      7499       1600

SQL>

結果の値のr列を取り除く方法は?

の代わりに select *、外部クエリに必要な列名をリストします。クエリを頻繁に使用する場合、ビューの作成は単純な1回限りのアクティビティです。

または、SQL*Plus[〜#〜] noprint [〜#〜]コマンドを使用できます。表示したくない列名は表示されません。ただし、SQL * Plusでのみ機能します。

例えば、

COLUMN column_name NOPRINT

例えば、

SQL> desc dept
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------
 DEPTNO                                             NUMBER(2)
 DNAME                                              VARCHAR2(14)
 LOC                                                VARCHAR2(13)

SQL> COLUMN dname NOPRINT
SQL> COLUMN LOC NOPRINT
SQL> SELECT * FROM dept;

    DEPTNO
----------
        10
        20
        30
        40

SQL>

正しいページ付けが保証されていますか?

はい、ページネーションクエリを正しく記述すれば可能です。

例えば、

SELECT val
FROM   (SELECT val, rownum AS rnum
        FROM   (SELECT val
                FROM   t
                ORDER BY val)
        WHERE rownum <= 8)
WHERE  rnum >= 5;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

SQL>

または、上に示したように、12cで新しい行制限機能を使用します。

いくつかの良い例 ここ

26
Lalit Kumar B

質問2への回答:Oracle 12では、ページネーションを使用できます

select owner, object_name, object_id
from t
order by owner, object_name
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;

私は通常、次のようなクエリを作成します。

select * 
from 
(
    select a.*, rownum as rn  
    from table_name a
    where rownum <= 110
)
where rn > 100 
3
Pavel Zimogorov