1204

OracleMySQLlimit句が含まれているようにクエリを動作させる方法はありますか?

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行のランダムなセットを返しますが、これは通常私が望むものではありません。また、オフセットを指定することもできません。

4

14 に答える 14

865

このようなサブクエリを使用できます

select *
from  
( select * 
  from emp 
  order by sal desc ) 
where ROWNUM <= 5;

詳細については、Oracle/AskTom のROWNUM および制限結果に関するトピックも参照してください。

更新:下限と上限の両方で結果を制限するには、もう少し肥大化します

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;

その他の例については、この回答を参照してください。ヒントをくれたクルミアに感謝します。

于 2009-01-22T19:55:58.797 に答える
809

Oracle 12c R1 (12.1) 以降で行制限句があります。使い慣れたLIMIT構文は使用しませんが、より多くのオプションを使用すると、より適切に機能します。ここで完全な構文を見つけることができます。(また、これが Oracle で内部的にどのように機能するかについては、こちらの回答を参照してください)。

元の質問に答えるために、クエリは次のとおりです。

SELECT * 
FROM   sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

(以前の Oracle バージョンについては、この質問の他の回答を参照してください)


例:

次の例は、リンクの腐敗を防ぐために、リンクされたページから引用されています。

設定

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;

COMMIT;

表には何がありますか?

SELECT val
FROM   rownum_order_test
ORDER BY val;

       VAL
----------
         1
         1
         2
         2
         3
         3
         4
         4
         5
         5
         6
         6
         7
         7
         8
         8
         9
         9
        10
        10

20 rows selected.

最初のN行を取得する

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

       VAL
----------
        10
        10
         9
         9
         8

5 rows selected.

最初のN行を取得します。行に同順位がある場合N、同順位のすべての行を取得します

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS WITH TIES;

       VAL
----------
        10
        10
         9
         9
         8
         8

6 rows selected.

行の上位x%

SELECT val
FROM   rownum_order_test
ORDER BY val
FETCH FIRST 20 PERCENT ROWS ONLY;

       VAL
----------
         1
         1
         2
         2

4 rows selected.

オフセットを使用すると、ページネーションに非常に役立ちます

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

オフセットとパーセンテージを組み合わせることができます

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 20 PERCENT ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.
于 2014-09-26T04:01:24.983 に答える
193

次のアプローチでいくつかのパフォーマンス テストを行いました。

アスクトム

select * from (
  select a.*, ROWNUM rnum from (
    <select statement with order by clause>
  ) a where rownum <= MAX_ROW
) where rnum >= MIN_ROW

分析的

select * from (
  <select statement with order by clause>
) where myrow between MIN_ROW and MAX_ROW

ショート オルタナティブ

select * from (
  select statement, rownum as RN with order by clause
) where a.rn >= MIN_ROW and a.rn <= MAX_ROW

結果

テーブルには 1,000 万件のレコードがあり、並べ替えはインデックスのない日時行で行われました。

  • Explain Plan が 3 つの選択すべてで同じ値を示した (323168)
  • しかし、勝者はAskTomです(分析がすぐ後ろに続きます)

最初の 10 行の選択には次の時間がかかりました。

  • アスクトム: 28 ~ 30 秒
  • 分析: 33 ~ 37 秒
  • 短い代替: 110 ~ 140 秒

100,000 から 100,010 の間の行を選択する:

  • アスクトム: 60 秒
  • 分析: 100 秒

9,000,000 から 9,000,010 の間の行を選択する:

  • アスクトム: 130 秒
  • 分析: 150 秒
于 2011-06-30T14:20:24.020 に答える
57

ネストされたクエリが 1 つだけの分析ソリューション:

SELECT * FROM
(
   SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
) 
WHERE MyRow BETWEEN 10 AND 20;

Rank()を代用することはできRow_Number()ますが、name の値が重複している場合、予想よりも多くのレコードが返される可能性があります。

于 2009-01-23T14:28:08.537 に答える
30

Oracle 12c の場合 ( SQL リファレンスの行制限句を参照):

SELECT * 
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
于 2013-09-24T03:09:56.120 に答える
18

Oracle では、順序付けを伴うページネーション クエリは非常に扱いにくいものです。

Oracle は、データベースがテーブルまたは一連の結合されたビューから行を選択する順序を示す数値を返す ROWNUM 疑似列を提供します。

ROWNUM は、多くの人を困らせる疑似列です。ROWNUM 値は行に永続的に割り当てられるわけではありません (これはよくある誤解です)。ROWNUM 値が実際に割り当てられると混乱する場合があります。ROWNUM 値は、行がクエリのフィルター述語を通過した後、クエリの集計または並べ替えの前に割り当てられます。

さらに、ROWNUM 値は、割り当てられた後にのみ増分されます。

これが、次のクエリが行を返さない理由です。

 select * 
 from (select *
       from some_table
       order by some_column)
 where ROWNUM <= 4 and ROWNUM > 1; 

クエリ結果の最初の行は ROWNUM > 1 述語を渡さないため、ROWNUM は 2 に増加しません。このため、ROWNUM 値が 1 より大きくなることはなく、その結果、クエリは行を返しません。

正しく定義されたクエリは次のようになります。

select *
from (select *, ROWNUM rnum
      from (select *
            from skijump_results
            order by points)
      where ROWNUM <= 4)
where rnum > 1; 

Vertabeloブログの記事で、ページネーション クエリの詳細を確認してください。

于 2014-04-12T17:32:50.717 に答える
6

少ない SELECT ステートメント。また、パフォーマンスの消費も少なくなります。クレジット: anibal@upf.br

SELECT *
    FROM   (SELECT t.*,
                   rownum AS rn
            FROM   shhospede t) a
    WHERE  a.rn >= in_first
    AND    a.rn <= in_first;
于 2011-03-02T14:32:32.123 に答える
3

Oracle 1z0-047 試験の準備を開始し、12c に対して検証されました。その準備をしているときに、「FETCH FIRST」と呼ばれる 12c の拡張機能に出会いました。これにより、都合に応じて行をフェッチしたり、行を制限したりできます。いくつかのオプションが利用可能です

- FETCH FIRST n ROWS ONLY
 - OFFSET n ROWS FETCH NEXT N1 ROWS ONLY // leave the n rows and display next N1 rows
 - n % rows via FETCH FIRST N PERCENT ROWS ONLY

例:

Select * from XYZ a
order by a.pqr
FETCH FIRST 10 ROWS ONLY
于 2016-06-01T10:31:02.940 に答える
-3

(テストされていない)このようなものが仕事をするかもしれません

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

並べ替えに使用できる分析関数のランクもあります。

于 2009-01-22T20:21:56.483 に答える