【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
関連記事