はじめに
Oracleには、取得するレコード数を制限するLIMIT句がないです。
その代わりにROWNUM疑似列というものが用意されており、LIMITの代用が可能です。
SELECT * FROM table WHERE ROWNUM <= 10;
問題点
ただORDER BYやGROUP BYを併用する場合、意図した結果となりません。
ソートやグループ化の前にROWNUMが行われるようです。
解決
ググると、FROM句をサブクエリとして、そこでORDER BYやGROUP BYすればいいようです。
SELECT
*
FROM
(SELECT * FROM table ORDER BY column)
WHERE
ROWNUM <= 10;
なるほど!
…ではあるんですが、面倒ですね。
さらにOFFSETを行いたい場合、ROW_NUMBER()ウィンドウ関数を使用して、下記のようにする必要があります。
ROW_NUMBER()で行番号を採番し、BETWEENで取得範囲を指定します。
SELECT
*
FROM
(
SELECT
table.*,
ROW_NUMBER() OVER (ORDER BY column) AS row_number
FROM
table
)
WHERE
row_number BETWEEN 1 AND 10;
さらに面倒ですね…
よりよい方法(条件付き)
Oracle 12c からFETCH FIRST句とOFFSET句が用意され、記述がとても楽になりました。
SELECT
*
FROM
table
ORDER BY column
FETCH FIRST 10 ROWS ONLY;
OFFSETを指定する場合。
SELECT
*
FROM
table
ORDER BY column
OFFSET 5 ROWS FETCH FIRST 10 ROWS ONLY;
感想
Oracle 12c 以降は簡潔に記述できるようになりましたが、LIMITとOFFSETに比べたらまだ煩雑ですね。
なぜ統一しないんでしょう…