SQL ROWNUM如何返回特定范围内的行

38

如何返回特定范围的ROWNUM值?

我正在尝试以下内容:

select * from maps006 where rownum >49 and rownum <101

这将仅返回与<操作符匹配的行。


7个回答

76
 SELECT * from
 (
 select m.*, rownum r
 from maps006 m
 )
 where r > 49 and r < 101

3
我的快速解决方法是将第一行更改为: SELECT col1,col2,col3 from其中,col1col2等将是除 r 列以外的所有列的名称。 - Dennis
2
如果您不给 ROWNUM 起别名,它在 Oracle 上无法正常工作。 - Julio Marins
2
如何在结果集中选择所有行而不使用rownum? - Vladimir
1
我在使用这个模式时,在Oracle中得到了不一致的结果。下面的双重嵌套查询修复了这个问题。 - geneorama
@Vladimir,在外部选择中去除*,并按照您要求进行列选择。(使用已接受的查询) - ram
显示剩余2条评论

34
SELECT  *
FROM    (
        SELECT  q.*, rownum rn
        FROM    (
                SELECT  *
                FROM    maps006
                ORDER BY
                        id
                ) q
        )
WHERE   rn BETWEEN 50 AND 100

注意双重嵌套视图。 ROWNUMORDER BY 之前被评估,因此对于正确的编号是必需的。

如果省略 ORDER BY 子句,则无法获得一致的顺序。


当我尝试类似的东西时,我会收到“ORA-00904:“RN”:无效标识符”的错误提示。 - Robin Green
@RobinGreen:请再提出一个问题,并在那里发布“类似的东西”。 - Quassnoi
我仍然不明白为什么需要双重嵌套。我正在尝试使用一些数据,并且它正在给我一致的记录。select * from (SELECT tab.*, rownum r FROM table1 tab order by cft.confrm_fraud_id) tab1 WHERE tab1.r BETWEEN 10 AND 20 - Ubercool
1
@pramod:这是因为你的查询按照confrm_fraud_id的顺序读取记录,很可能使用了它的索引。你不能依赖这种行为。比较一下这两个查询:http://sqlfiddle.com/#!4/4730c5/5(不正确)和http://sqlfiddle.com/#!4/4730c5/7(正确)。请注意,在不正确的查询中,`ROWNUM`甚至出现在错误的顺序中。 - Quassnoi
这个解决方案对我非常有效。我试图在一个有12行的结果集上使用ROWNUM BETWEEN 11 AND 20进行分页,但是对于任何以>1开头的范围都会得到0条记录。感谢您的提示! - cyberbit
显示剩余2条评论

22

我知道这是一个老问题,然而,提到最新版本中的新功能仍然很有用。

Oracle 12c开始,您可以使用新的Top-n Row limiting feature。无需编写子查询,在ROWNUM上没有依赖性。

例如,下面的查询将按升序返回第4高到第7高薪水之间的员工:

SQL> SELECT empno, sal
  2  FROM   emp
  3  ORDER BY sal
  4  OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

     EMPNO        SAL
---------- ----------
      7654       1250
      7934       1300
      7844       1500
      7499       1600

SQL>

6
我正在寻找一个解决方案,找到了这篇很棒的文章解释解决方案。相关摘录如下:

我所有时间最喜欢使用 ROWNUM 是分页。在这种情况下,我使用 ROWNUM 来获取结果集中第 N 至 M 行的行。其一般形式如下:

select * enter code here
  from ( select /*+ FIRST_ROWS(n) */ 
  a.*, ROWNUM rnum 
      from ( your_query_goes_here, 
      with order by ) a 
      where ROWNUM <= 
      :MAX_ROW_TO_FETCH ) 
where rnum  >= :MIN_ROW_TO_FETCH;

现在有一个真实的例子(获取第148、149和150行):
select *
    from
  (select a.*, rownum rnum
     from
  (select id, data
     from t
   order by id, rowid) a
   where rownum <= 150
  )
   where rnum >= 148;

2
SELECT * FROM
(SELECT ROW_NUMBER() OVER(ORDER BY Id) AS RowNum, * FROM maps006) AS DerivedTable
WHERE RowNum BETWEEN 49 AND 101

2
您可以使用CTE语句进行操作。
WITH maps AS (Select ROW_NUMBER() OVER (ORDER BY Id) AS rownum,* 
from maps006 )

SELECT rownum, * FROM maps  WHERE rownum >49 and rownum <101  

2
select * 
from emp 
where rownum <= &upperlimit 
minus 
select * 
from emp 
where rownum <= &lower limit ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接