【Oracle SQL*Plus】ROWNUM指定による行取得で期待されるレコードが取得出来ない。【トラブルシューティング】

雑学

備忘録になります。ROWNUM指定による行取得で期待されるレコードが取得出来ないケースについてまとめました。

ケース①:違うレコードが取得された

SQL> SELECT * FROM TEST_TABLE
  2  ORDER BY ID;
         1,NAME-A    ,         1,A
         2,NAME-B    ,         2,B
         3,NAME-C    ,         3,C
         4,NAME-D    ,         4,D
         5,NAME-E    ,         5,E

SQL> SELECT * FROM TEST_TABLE
  2  WHERE ROWNUM <= 3
  3  ORDER BY ID;
         2,NAME-B    ,         2,B
         3,NAME-C    ,         3,C
         4,NAME-D    ,         4,D

IDが1~3のレコードを表示させたいが、ソートが効かず、2~4が表示されている。WHERE句に利用する場合、ORDER BYやGROUP BYより優先順位が高いため、ソート後やグループ化後の結果に対しての行番号を使いたい場合は工夫が必要です。解決法として、私はサブクエリを使って回避しています。

SQL> SELECT * FROM (
  2    SELECT * FROM TEST_TABLE
  3    ORDER BY ID)
  4  WHERE ROWNUM <= 3;
         1,NAME-A    ,         1,A
         2,NAME-B    ,         2,B
         3,NAME-C    ,         3,C

ケース②:レコードが取得できない

SQL> SELECT * FROM TEST_TABLE;
         2,NAME-B    ,         2,B
         3,NAME-C    ,         3,C
         4,NAME-D    ,         4,D
         5,NAME-E    ,         5,E
         1,NAME-A    ,         1,A

SQL> SELECT * FROM TEST_TABLE
  2  WHERE ROWNUM = 3

レコードが選択されませんでした。

「ROWNUM = 3」のような指定は期待通り表示されません。ROWNUM = 1からチェックされ、条件を満たされない時点で表示終了する仕様のようです。解決策としてはソート済な項目に対し、ORDER BYを使って表示を逆転させてから先頭行を取る工夫をします。

SQL> SELECT * FROM (
  2    SELECT * FROM TEST_TABLE
  3    WHERE ROWNUM <= 3
  4    ORDER BY ID DESC)
  5  WHERE ROWNUM = 1;
         4,NAME-D    ,         4,D

関連記事