如何在订购后限制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万条记录,排序在一个没有建立索引的日期时间行上:
选择前10行:
选择100,000到100,010之间的行:
选择9,000,000和9,000,010之间的行:
上一篇: How do I limit the number of rows returned by an Oracle query after ordering?