【问题标题】:How can I select the record with the 2nd highest salary in database Oracle?如何选择数据库 Oracle 中薪水第二高的记录?
【发布时间】:2013-04-30 06:08:12
【问题描述】:

假设我有一个表employee,id、user_name、salary。如何选择Oracle中薪水第二高的记录?

我google了一下,找到了这个解决方案,是这样的吗?:

select sal from
     (select rownum n,a.* from
        ( select distinct sal from emp order by sal desc) a)
where n = 2;

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    已经建议了 RANK 和 DENSE_RANK - 根据您的要求,您还可以考虑 ROW_NUMBER():

    select * from (
      select e.*, row_number() over (order by sal desc) rn from emp e
    )
    where rn = 2;
    

    RANK()、DENSE_RANK() 和 ROW_NUMBER() 的区别归结为:

    • ROW_NUMBER() 总是生成唯一的排名;如果 ORDER BY 子句不能区分两行,它仍然会给它们不同的排名(随机)
    • RANK() 和 DENSE_RANK() 将为 ORDER BY 子句无法区分的行提供相同的排名
    • DENSE_RANK() 将始终生成连续的排名序列 (1,2,3,...),而 RANK() 将在具有相同排名的两行或多行之后留下空白(想想“奥运会”:如果两名运动员获得金牌,没有第二名,只有第三名)

    因此,如果您只想要一名员工(即使有几名员工的薪水第二高),我建议您使用 ROW_NUMBER()。

    【讨论】:

    • +1 以“奥林匹克运动会”示例很好地理解了 RANK 和 DENSE_RANK 之间的关系。
    • 如果两个员工的最高薪水相同,上面的row_number()函数查询会给出错误的结果。我们可以通过dense_rank() 解析函数得到想要的结果。
    • @TarunKumar 正如我在回答中提到的那样 - 根据您的要求,您需要 rank / dense_rank 来获得所有薪水最高的员工,或者 row_number 如果您想确保始终获得正好一条记录。
    【解决方案2】:

    如果您使用的是 Oracle 8+,则可以像这样使用 RANK()DENSE_RANK() 函数

    SELECT *
    FROM (
      SELECT some_column, 
             rank() over (order by your_sort_column desc) as row_rank
    ) t
    WHERE row_rank = 2;
    

    【讨论】:

    • 我打错了 9,意思是 8,已更正。感谢您指出!
    • NB 此查询可以返回多行,而问题中发布的查询将返回不同的过滤重复项。
    【解决方案3】:

    此查询在 SQL*PLUS 中工作,以找出 第二高薪水 -

    SELECT * FROM EMP
    WHERE SAL = (SELECT MAX(SAL) FROM EMP
    WHERE SAL < (SELECT MAX(SAL) FROM EMP));
    

    这是双重子查询

    希望对你有帮助..

    【讨论】:

      【解决方案4】:
      WITH records
      AS
      (
          SELECT  id, user_name, salary,
                  DENSE_RANK() OVER (PARTITION BY id ORDER BY salary DESC) rn
          FROM    tableName
      )
      SELECT  id, user_name, salary
      FROM    records 
      WHERE   rn = 2
      

      【讨论】:

        【解决方案5】:

        你应该使用这样的东西:

        SELECT *
        FROM (select salary2.*, rownum rnum from
                 (select * from salary ORDER BY salary_amount DESC) salary2
          where rownum <= 2 )
        WHERE rnum >= 2;
        

        【讨论】:

        • 为什么一定要用“rnum=2”,不能只说“rnum=2”吗?
        • @user1801838 不可以。你不能使用 rownum with = n for n > 1(事实上你可以,但它总是返回一个空的结果集)。
        【解决方案6】:
        select * from emp where sal=(select max(sal) from emp where sal<(select max(sal) from emp))
        

        所以在我们的emp表中(默认由oracle提供)这里是输出

        EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO


          7698 BLAKE      MANAGER         7839 01-MAY-81       3000            30
          7788 SCOTT      ANALYST         7566 19-APR-87       3000            20
          7902 FORD       ANALYST         7566 03-DEC-81       3000            20
        

        或者只是您希望显示第二个最高薪水

        select max(sal) from emp where sal<(select max(sal) from emp)
        

        最大(SAL)

          3000
        

        【讨论】:

        • 请学习使用格式标签并使用它们使答案可读:-)
        【解决方案7】:
        select * FROM (
        select EmployeeID, Salary
        , dense_rank() over (order by Salary DESC) ranking
        from Employee
        )
        WHERE ranking = 2;
        

        dense_rank() 用于薪水必须相同。所以它给出正确的输出而不是使用 rank()

        【讨论】:

          【解决方案8】:

          选择 Max(Salary) 作为 SecondHighestSalary from Employee where Salary not in (从 Employee 中选择 max(Salary))

          【讨论】:

            【解决方案9】:

            我建议以下两种方法在 Oracle 中实现这一点。

            1. 使用子查询:
            select distinct SALARY   
            from EMPLOYEE e1  
            where 1=(select count(DISTINCT e2.SALARY) from EMPLOYEE e2 where         
              e2.SALARY>e1.SALARY);
            

            这是获取所需输出的非常简单的查询。但是,这个查询非常慢,因为内部查询中的每个薪水都会与所有不同的薪水进行比较。

            1. 使用 DENSE_RANK():
            select distinct SALARY   
            from
              (
                select e1.*, DENSE_RANK () OVER (order by SALARY desc) as RN 
                from EMPLOYEE e
              ) E
             where E.RN=2;
            

            这是非常有效的查询。它与 DENSE_RANK() 配合使用效果很好,它分配连续的排名,而 RANK() 则根据行号分配下一个排名,就像奥运会奖牌一样。

            RANK() 和 DENSE_RANK() 的区别: https://oracle-base.com/articles/misc/rank-dense-rank-first-last-analytic-functions

            【讨论】:

              【解决方案10】:

              我相信这将实现相同的结果,无需子查询或排名函数:

              SELECT *
              FROM emp
              ORDER BY sal DESC
              LIMIT 1
              OFFSET 2
              

              【讨论】:

              • 仅供参考,Oracle数据库中没有LIMIT关键字,其次,如果两个员工的最高工资相同,则会给出错误的结果。我们可以通过dense_rank() 解析函数得到想要的结果。
              【解决方案11】:

              此查询每次都可以帮助我解决此类问题。将 N 替换为位置..

              select *
              from(
                   select *
                   from (select * from TABLE_NAME order by SALARY_COLUMN desc)
                   where rownum <=N
                  )
              where SALARY_COLUMN <= all(
                              select SALARY_COLUMN
                              from (select * from TABLE_NAME order by SALARY_COLUMN desc)
                              where rownum <=N
                             );
              

              【讨论】:

                【解决方案12】:
                select * from emp where sal = (
                select sal from
                     (select rownum n,a.sal from
                    ( select distinct sal from emp order by sal desc) a)
                where n = 2);
                

                这样更优化,适合所有场景...

                【讨论】:

                  【解决方案13】:
                  select max(Salary) from EmployeeTest where Salary < ( select max(Salary) from EmployeeTest ) ;
                  

                  这适用于所有数据库。

                  【讨论】:

                    【解决方案14】:

                    您可以使用两个 max 函数。假设从 SALARY_TBL 中获取 userid=10 及其第二高薪水的数据。

                    select max(salary) from SALARY_TBL
                    where 
                    userid=10
                    salary <> (select max(salary) from SALARY_TBL where userid=10)
                    

                    【讨论】:

                      【解决方案15】:

                      用你的最大数替换 N

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

                      解释

                      如果您以前没有见过类似的查询,上面的查询可能会很混乱 - 内部查询是所谓的相关子查询,因为内部查询(子查询)使用来自外部查询的值(在这种情况下Emp1 表)在它的 WHERE 子句中。

                      还有Source

                      I have given the answer here

                      顺便说一下,我将此问题标记为重复。

                      【讨论】:

                      • -1。具有 107 行的示例 hr.employees 表的 361 次一致获取。
                      • 没有错误,从性能的角度来看,您的方法非常不理想。例如@hd1 的查询只读取 6 个块
                      【解决方案16】:

                      Sql server 的语法

                      SELECT MAX(Salary) as 'Salary' from EmployeeDetails
                      where Salary NOT IN
                      (
                      SELECT TOP n-1 (SALARY) from EmployeeDetails ORDER BY Salary Desc
                      )
                      

                      要获得员工的第二高薪,我们需要将“n”替换为 2,我们的查询将是这样的

                      SELECT MAX(Salary) as 'Salary' from EmployeeDetails
                      where Salary NOT IN
                      (
                      SELECT TOP 1 (SALARY) from EmployeeDetails ORDER BY Salary Desc
                      )
                      

                      员工薪水第三高

                      SELECT MAX(Salary) as 'Salary' from EmployeeDetails
                      where Salary NOT IN
                      (
                      SELECT TOP 2 (SALARY) from EmployeeDetails ORDER BY Salary Desc
                      )
                      

                      【讨论】:

                        【解决方案17】:
                        SELECT * FROM EMP WHERE SAL=(SELECT MAX(SAL) FROM EMP WHERE SAL<(SELECT MAX(SAL) FROM  EMP));
                        

                        (或)

                        SELECT ENAME ,SAL  FROM EMP  ORDER BY SAL DESC;
                        

                        (或)

                        SELECT * FROM(SELECT ENAME,SAL ,DENSE_RANK() 
                        OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) R FROM EMP) WHERE R=2;
                        

                        【讨论】:

                        【解决方案18】:
                        select salary from EmployeeDetails order by salary desc limit 1 offset (n-1).
                        

                        如果您想找到第二高的,而不是将 n 替换为 2

                        【讨论】:

                          猜你喜欢
                          • 2019-04-17
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-12-04
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-01-30
                          • 1970-01-01
                          • 2011-12-20
                          相关资源
                          最近更新 更多