如何在订购后限制Oracle查询返回的行数?

有没有办法让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行按名称排序,这通常不是我想要的。 它也不允许指定偏移量。


从Oracle 12c R1(12.1)开始,有一个行限制子句。 它不使用熟悉的LIMIT语法,但可以通过更多选项更好地完成这项工作。 你可以在这里找到完整的语法。

要回答原始问题,请查询以下内容:

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.

你可以像这样使用子查询

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

还可以看看On ROWNUM主题,并在Oracle / AskTom中限制结果以获取更多信息。

更新 :为了限制结果的下限和上限,事情会变得更加臃肿

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的提示。


我为以下方法做了一些性能测试:

Asktom

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

结果

表有1000万条记录,排序在一个没有建立索引的日期时间行上:

  • 解释计划对所有三个选择显示相同的值(323168)
  • 但胜利者是AskTom(分析后紧随其后)
  • 选择前10行:

  • AskTom:28-30秒
  • 分析:33-37秒
  • 短的选择:110-140秒
  • 选择100,000到100,010之间的行:

  • AskTom:60秒
  • 分析:100秒
  • 选择9,000,000和9,000,010之间的行:

  • AskTom:130秒
  • 分析:150秒
  • 链接地址: http://www.djcxy.com/p/36907.html

    上一篇: How do I limit the number of rows returned by an Oracle query after ordering?

    下一篇: Ruby/Rails: converting a Date to a UNIX timestamp