使用sql计算最高第n个工资

时间:2017-06-24 15:19:51

标签: sql oracle top-n

我想计算Oracle中最高的第n个工资。我已经完成了我的解决方案,但在谷歌上我发现一个查询做了同样的事情。

这是查询

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

数据

   ID   Name    Birth       Orig_Salary
    2   John    15-JUL-97   2341    
    3   Joe     25-JAN-86   4321    
    4   Tom     13-SEP-06   2413    
    5   Jane    17-APR-05   7654    
    6   James   18-JUL-04   5679    
    7   Jodd    20-JUL-03   5438    
    8   Joke    01-JAN-02   8765    
    9   Jack    29-AUG-01   7896

我无法理解这个查询。 在运行内部查询之后,它总是会给我8个数字,这样做会转到where子句,它将选择高于外部查询工资的工资。内部和外部查询之间的运算符如何相等以及如何进行比较。

有没有人可以帮助我理解这个查询在后端技术上是如何工作的?

2 个答案:

答案 0 :(得分:2)

SELECT *
FROM Employee Emp1
WHERE (N - 1) = (SELECT COUNT(DISTINCT(Emp2.orig_salary))
                FROM Employee Emp2  <--- cartesian product with same table
                WHERE emp2.orig_salary > emp1.orig_salary)  <---- but  do the cartesian product only if line of salary of emp 2 is greater than the current line of Emp1 'salary 

例如假设表中只有3行:

ID Name Birth Orig_Salary

2   John    15-JUL-97   2341    
3   Joe     25-JAN-86   4321    
4   Tom     13-SEP-06   5413 

主查询将查看第一行 - &gt; 2 John 15-JUL-97 2341&lt; ---,子查询将返回2,因为工资4321(emp2.​​orig_salary)和5413(emp2.​​orig_salary)大于2341(emp1.orig_salary)

然后主查询将查看第二行 - &gt; 3 Joe 25-JAN-86 4321&lt; ---,并且子查询将返回1,因为工资5413(emp2.​​orig_salary)大于2341(emp1.orig_salary)

当我说子查询时,它就是

=(SELECT COUNT(DISTINCT(Emp2.orig_salary))
                 FROM Employee Emp2  <--- cartesian product with same table
                WHERE emp2.orig_salary > emp1.orig_salary)

,主要查询是

SELECT *
FROM Employee Emp1
WHERE 

然后将子查询返回的值与where条件n-1进行比较,如果满足条件,则检索该行。

答案 1 :(得分:1)

无需了解该查询。正确的表述是:

SELECT Emp1.*
FROM (SELECT Emp1.*, DENSE_RANK() OVER (ORDER BY Emp2.orig_salary) as seqnum
      FROM Employee Emp1
     ) Emp1
WHERE seqnum = <n>;

这提供了员工的详细信息。如果你只想要薪水:

SELECT orig_salary
FROM (SELECT Emp1.*, DENSE_RANK() OVER (ORDER BY Emp2.orig_salary) as seqnum
      FROM Employee Emp1
     ) Emp1
WHERE seqnum = <n> AND rownum = 1;

我应该注意到一个更简单的版本是:

select distinct orig_salary
from employees
order by orig_salary desc
offset <n - 1>
fetch first 1 row only;

从关系数据库不像现在这样强大的时代开始,使用相关子查询是一个令人愉快的时代错误。这具有历史意义。