小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


Oracleでrownum order byを使ったページング処理の注意点


photo credit: Silvia Sala via photopin cc

はじめに

Oracleでページング処理を実装するときに、rownumの性質を正しく理解していなかったため、ソート指定した際にハマりました。
この記事では、Oracleでrownumを使ったページング処理の書き方を調べてまとめてみました。

事前準備

以下のようなテーブルを用意します。

create table table01
(
  id number,
  name varchar(50),
  furigana varchar(50),
  birthday varchar(8),
  primary key( id )
);

データはこんな感じです。

rownumはソートする前に番号がふられる

擬似的な列番号を返してくれるrownumですが、ソート指定がない場合は取得結果の先頭から連番がふられます。

select rownum, name, birthday from table01;

しかし、生年月日でソートした場合、rownumの結果が逆転してしまいます。これはrownumがselectした時点でふられており、その後にソート処理が行われているからです。

select rownum, name, birthday from table01 order by birthday desc;


ソート指定で先頭から連番をふる

上記のように、rownumはselectした時点でふられてしまうので、副問い合わせを使ってソート済みの結果に対してrownumをふるという方法を使います。

select rownum, t01.name, t01.birthday from (
  select name, birthday from table01 order by birthday desc) t01;


ページング処理で指定した箇所からn件取得する

ページング処理では、1件目から20件目、次ページでは21件目から40件目というように、指定した箇所からn件取得する必要があります。こうした場合、between句で範囲を指定します。
さきほどのクエリを副問い合わせに指定して、rownumに別名を与えます。親のクエリ側でbetween句を指定してあげることで指定した箇所からn件のレコードを取得することができます。

select * from   
  (select rownum rownumber, t01.name, t01.birthday from 
    (select name, birthday from table01 order by birthday desc) t01
  ) t01x
where rownumber between 2 and 4;