【问题标题】:How to find the employee with the second highest salary?如何找到薪水第二高的员工?
【发布时间】:2011-01-30 06:27:09
【问题描述】:

是否有任何预定义的函数或方法可用于从员工表中获取第二高的薪水?

【问题讨论】:

    标签: sql oracle top-n


    【解决方案1】:

    试试这个:

    SELECT * FROM employee emp WHERE 2=(SELECT COUNT(*) FROM employee WHERE
    salary >= emp.salary);
    

    【讨论】:

    • -1 我不确定这会返回什么,但可能不是问题所在:-)
    • 这取决于他对“方法”的含义。对我来说,方法是获得结果的过程;这是我建议的方法。感谢我的第一次投反对票:)。
    • @Aaron:也许不是返回结果的最有效方式(因为它使用自联接)但它会返回正确的答案,如果薪水是唯一的(例如,如果三个人的最高薪水相同,它将不起作用)。
    【解决方案2】:

    在 Oracle 中,您将使用这样的查询来返回分页结果(行 M 到 N):

    SELECT NAME, salary
      FROM (SELECT NAME, salary, ROWNUM r 
              FROM (SELECT NAME, salary 
                      FROM employee 
                     ORDER BY salary DESC
                    )
             WHERE ROWNUM <= :N
            )
     WHERE r >= :M
    

    或者,您可以使用分析:

    SELECT NAME, salary
      FROM (SELECT NAME, salary, row_number() over (ORDER BY salary DESC) n 
              FROM employee)
     WHERE n BETWEEN :M AND :N
    

    【讨论】:

      【解决方案3】:

      执行此操作的方法是使用 Oracle 的分析功能。您的特定场景只是我在another thread 中提供的解决方案的一种变体。

      如果您只想选择第二高的薪水,那么 DENSE_RANK()、RANK() 和 ROW_NUMBER() 中的任何一个都可以解决问题:

      SQL> select * from
        2   ( select sal
        3            , rank() over (order by sal desc) as rnk
        4     from
        5      ( select distinct sal
        6        from emp )
        7    )
        8  where rnk = 2
        9  /
      
             SAL        RNK
      ---------- ----------
            3000          2
      
      SQL> 
      

      但是,如果您要选择附加信息,例如薪水第二高的员工的姓名,您选择的功能会影响结果。选择一个而不是另一个的主要原因是出现平局时会发生什么。

      如果您使用 ROW_NUMBER(),它将返回按薪水排序的第二名员工:如果有两名员工并列最高薪水怎么办?如果有两名员工并列第二高的薪水怎么办?如果您使用 RANK() 并且有两个员工并列第一高薪,那么将有 no 记录 RANK = 2。

      我建议 DENSE_RANK() 通常是在这些情况下选择最安全的函数,但它确实取决于特定的业务需求。

      【讨论】:

        【解决方案4】:

        如果你想从表中找出n个最高的薪水,你可以这样:

        select min(sal)from (select distinct sal from emp order by sal desc) where rownum<=n;
        

        其中 n 是 1,2,3, ..., n

        从表格中找出最高工资是一个非常简单的过程。

        【讨论】:

          【解决方案5】:

          使用Oracle DB 12c 处理Top-N 查询更容易,它引入了这样的语法:

          [ OFFSET offset { ROW | ROWS } ]
          [ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
              { ROW | ROWS } { ONLY | WITH TIES } ]
          

          用于ORDER BY 列表之后的查询。

          在这种情况下考虑使用:

          select *
            from emp
           order by sal desc
          offset 1 rows fetch next 1 rows only
          

          其中使用offset 是可选的,从语法中已经可以看出,并指出fetch 子句的起点将是offset + 1

          一个特殊情况是ties,这意味着多行匹配第 N 行的值(这里我们需要第 2 行)。如果第二名的薪水相同的人不止一个,那么我们需要将only关键字替换为with ties以全部返回:

          select *
            from emp
           order by sal desc
          offset 1 rows fetch next 1 rows with ties
          

          Demo

          【讨论】:

            猜你喜欢
            • 2011-12-20
            • 1970-01-01
            • 2019-04-17
            • 1970-01-01
            • 2011-01-10
            • 1970-01-01
            • 2014-09-02
            • 2020-01-29
            • 1970-01-01
            相关资源
            最近更新 更多