带有rownum< =的oracle sql

时间:2014-01-31 15:24:34

标签: sql oracle

如果我从查询中移除<符号,则以下查询未提供结果的原因。因为即使没有<它也必须与结果匹配?

用于获取第二个最大ID值的查询:

select min(id) 
from(
    select distinct id 
    from student 
    order by id desc
) 
where rownum <=2


student id 
1
2
3
4

6 个答案:

答案 0 :(得分:6)

Rownum在Oracle中具有特殊含义。它随着每一行而增加,但优化器知道它会不断增加,并且所有连续的行必须满足rownum条件。因此,如果您指定rownum = 2,它将永远不会发生,因为第一行已被拒绝。

如果您对查询执行解释计划,您会发现这非常好。它将显示如下内容:

计划rownum <=

COUNT STOPKEY       

计划rownum =

FILTER

答案 1 :(得分:1)

ROWNUM值未永久分配给一行(这是一种常见的误解)。表中的一行没有数字;你不能要求表格中的第2行或第3行  点击Here了解更多信息。

这是来自提供的链接:

对许多人来说,当实际分配ROWNUM值时也会感到困惑。 ROWNUM值在通过查询的谓词阶段之后但在查询执行任何排序或聚合之前分配给行。此外,ROWNUM值仅在分配后递增,这就是以下查询永远不会返回行的原因:

select * 
 from t 
 where ROWNUM > 1;

因为ROWNUM&gt; 1对于第一行不成立,ROWNUM不会前进到2.因此,ROWNUM值不会大于1.考虑具有此结构的查询:

select ..., ROWNUM
from t
where <where clause>
group by <columns>
having <having clause>
order by <columns>;

答案 2 :(得分:1)

我认为这是您正在寻找的查询:

select id
from (select distinct id
      from student
      order by id desc
     ) t
where rownum <= 2;

Oracle在rownum之前处理order by,因此您需要一个子查询来获取前两行。 min()强制执行仅返回一个结果的聚合,但在应用rownum之前。

如果您实际只想要第二个值,则需要一个额外的子查询层:

select min(id)
from (select id
      from (select distinct id
            from student
            order by id desc
           ) t
      where rownum <= 2
     ) t;

但是,我会这样做:

select id
from (select id, dense_rank() over (order by id) as seqnum
      from student
     ) t
where seqnum = 2;

答案 3 :(得分:0)

为什么不使用

select  id
from    ( select distinct id
          ,      row_number() over (order by id desc) x
          from   student
        )
where   x = 2

甚至非常糟糕。获取计数和索引:)

select  id
from    ( select id
          ,      row_number() over (order by id desc) idx
          ,      sum(1) over (order by null) cnt
          from   student
          group
          by     id
        )
where   idx = cnt - 1 -- get the pre-last

或者

where   idx = cnt - 2 -- get the 2nd-last

或者

where   idx = 3 -- get the 3rd

答案 4 :(得分:0)

订购asc而不是desc

select id from student where rownum <=2 order by id asc;

答案 5 :(得分:0)

试试这个

SELECT * 
FROM (
  SELECT id, row_number() over (order by id asc) row_num
  FROM student
     ) AS T
WHERE row_num = 2 -- or 3 ... n

ROW_NUMBER