Oracle」のクエリが「MySQL」の「limit」句を含んでいるように動作させる方法はありますか?
MySQL`ではこのようなことができます。
select *
from sometable
order by name
limit 20,10
とすると、21行目から30行目までを取得することができます(最初の20行はスキップして、次の10行を取得します)。行は order by
の後に選択されるので、実際にはアルファベット順で20番目の名前から始まります。
Oracleでは、
rownumという疑似カラムだけが言及されていますが、これは
order by` の前*に評価されるので、次のようになります。
select *
from sometable
where rownum <= 10
order by name
は名前順に並んだ10行のランダムなセットを返しますが、これは通常私が望むものではありません。また、オフセットを指定することもできません。
これには、次のようなサブクエリを使用できます。
select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;
詳細については、Oracle/AskTomのトピックOn ROWNUM and limiting resultsも参照してください。
更新: 下限と上限の両方で結果を制限するには、次のようにすると少し肥大化します。
select * from
( select a.*, ROWNUM rnum from
( <your_query_goes_here, with order by> ) a
where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
(特定のAskTomの記事からコピー)
アップデート2です。 Oracle 12c (12.1)では、行を制限したり、オフセットで開始するための構文が用意されています。
SELECT *
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
詳しい例はこの回答を参照してください。ヒントをくださったKrumiaさんに感謝します。
1つのネストされたクエリのみを使用した分析的ソリューション。
SELECT * FROM
(
SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
)
WHERE MyRow BETWEEN 10 AND 20;
Row_Number()の代わりにRank()
を使うこともできますが、nameに重複した値がある場合、期待したよりも多くのレコードを返すかもしれません。
(試していませんが、このようなものが仕事をするかもしれません。
WITH
base AS
(
select * -- get the table
from sometable
order by name -- in the desired order
),
twenty AS
(
select * -- get the first 30 rows
from base
where rownum < 30
order by name -- in the desired order
)
select * -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name -- in the desired order
また、解析的な関数であるrankもあり、これを使って順序付けすることができます。