【问题标题】:How to use rownum [duplicate]如何使用rownum [重复]
【发布时间】:2013-04-12 04:34:53
【问题描述】:

我在 oracle 中有一个员工表,其中包含姓名、薪水和其他详细信息。

我想拿第二高的薪水却拿不到。

这个很好用

with e_salary as (select distinct salary from employee)
select salary from e_salary
order by salary desc

并给出输出:

450000

61000

60000

50000

40000

30000

20000

6000

但是当我使用相同的查询来获取第二高的行时没有得到任何输出

select salary
  from ( with e_salary as (select distinct salary from employee)
         select salary from e_salary order by salary desc)
 where rownum = 2

但是当我将rownum=2 替换为rownum<2 时,它会给出前两条记录的输出。请有人解释为什么rownum=2 不起作用

【问题讨论】:

  • 这个问题有很多答案,请参阅hereherehere

标签: sql oracle rownum


【解决方案1】:

这将起作用:

从 ( 选择薪水 , rownum as rn from (选择薪水 从 e_salary order by sale dec)) where rn = 2;

为什么它不起作用:

给一行赋值ROWNUM时,Oracle从1开始,只有在选择一行时才增加值;也就是说,当 WHERE 子句中的所有条件都满足时。由于我们的条件要求 ROWNUM 大于 2,因此不会选择任何行,并且 ROWNUM 的增量永远不会超过 1。

希望你现在清楚。

【讨论】:

    【解决方案2】:
    select ename  ,sal  ,rank() over (order by sal desc) ranking from emp;
    

    试试这个。

    点击这个链接,关于第 n 行的所有内容都在 oracle 中给出:

    http://www.oratable.com/nth-highest-salary-in-oracle/

    【讨论】:

    • 如果第一个有双向并列,则第二高的薪水将被分配到 RANK3。我在最初的答案中使用了RANK,然后记住了这个小金块并将其更改为DENSE_RANK
    • 是的,我知道。由于 Rank() 可以是替代方法之一,我已经提供了 Rank() 的答案,然后给出了操作员链接,在该链接上,在 oracle 中有所有可能的替代方法,包括 DENSE_RANK。
    • 很抱歉;我应该检查你的链接。 +1 让我打开 oratable 网站 - 我花了几分钟浏览它,那里有一些很棒的信息。
    【解决方案3】:

    使用rownum 是一件棘手的事情。最安全的选择是仅在您想限制要显示的结果数量时使用它。例如 rownum

    为什么 rownum=2 不起作用?

    在这里阅读 - http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

    总而言之,这就是 oracle 执行查询的方式

    1. FROM/WHERE 子句先出现。
    2. ROWNUM 从 FROM/WHERE 子句分配并递增到每个输出行。
    3. 已应用 SELECT。
    4. 已应用 GROUP BY。
    5. HAVING 已应用。
    6. 已应用 ORDER BY。

    rownum

    ROWNUM = 1
    for x in 
    ( select * from emp )
    loop
        exit when NOT(ROWNUM <= 2)
        OUTPUT record to temp
        ROWNUM = ROWNUM+1
    end loop
    SORT TEMP
    

    如果你在 NOT(ROWNUM

    所以如果我不能使用 rownum,我可以使用什么。尝试使用 row_number() http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm

    它的工作原理类似于

    SELECT last_name FROM 
       (SELECT last_name, ROW_NUMBER() OVER (ORDER BY last_name) R FROM employees)
       WHERE R BETWEEN 51 and 100;
    

    【讨论】:

      【解决方案4】:

      rownum 在第一次失败时停止评估。在返回的第一行,rownum 为 1,因此它未能通过 rownum = 2 测试并停止尝试。有一篇关于它的精彩帖子here

      要获得第二高的薪水,使用Oracle解析DENSE_RANK函数:

      SELECT DISTINCT Salary FROM (
        SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS SalaryRank
        FROM e_salary)
      WHERE SalaryRank = 2
      

      请注意,如果第二次出现平局,则查询可能会返回多个值。这就是为什么外部的SELECTSELECT DISTINCT

      【讨论】:

        【解决方案5】:

        首先您应该了解rownum 是什么。让我举个例子,

         you want to get data with a filter and rownum=2, 
         first Oracle executes the sql with filter and get the first record, 
         give it the rownum 1, 
         and then compare it the rownum filter rownum=2, which doesn't match, so discard record, 
         then get second record, give it rownum=1(if the first record is matched then the rownum will  be 2)  too, then do the compare............ 
        

        这样你就可以找到原因了。

        【讨论】:

          【解决方案6】:

          不使用 rownum 命令,您可以使用此查询获得第二高的薪水:

          select MAX(Salary) from Employee 
          WHERE Salary NOT IN 
          (select MAX(Salary) from Employee )
          

          或者,

          select MAX(Salary) from Employee 
          WHERE Salary <> 
          (select MAX(Salary) from Employee )
          

          查询第 n 高:

          SELECT * FROM Employee Emp1 
          WHERE (N-1) = 
          (SELECT COUNT(DISTINCT(Emp2.Salary))FROM Employee Emp2 
          WHERE Emp2.Salary > Emp1.Salary)
          

          【讨论】:

            【解决方案7】:

            据我了解,rownum 为结果集中的行编号。

            所以,在你的例子中:

            select * from table1 where rownum=2

            结果集中会有多少行?因此,应该为这样的行分配什么 rownum?你现在能明白为什么实际上没有返回任何结果吗?

            一般来说,您应该避免依赖 rownum 或任何暗示结果顺序的功能。尝试考虑使用整个结果集。

            话虽如此,我相信以下方法会起作用:

            select * from (select rownum as rn,table1.* from table1) as t where t.rn = 2

            因为在这种情况下,您正在为子查询中的行编号。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-06-25
              • 2020-05-11
              • 2017-09-06
              • 1970-01-01
              • 2014-04-09
              相关资源
              最近更新 更多