SQL中的第N个薪水

问题描述 投票:1回答:3

我试图理解下面的查询,它是如何工作的。

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

假设我有5个不同的薪水,并希望获得3rd个最大的薪水。因此,内部查询将首先运行,然后外部查询?

我很困惑在sql引擎中是如何完成的。好奇地知道。因为如果3rd最大,然后3-1 = 2,那么2也需要与内部计数匹配。内部计数的操作方式。

谁能解释它是如何工作的..?

sql oracle subquery greatest-n-per-group
3个回答
1
投票

子查询是correlated子查询,因此从概念上讲,它对外部查询中的每一行执行一次(数据库优化未列出)。它的作用是计算多少员工的薪水高于该行的薪水。在外部查询中:如果有2名员工的薪水更高,则您知道外部查询中当前行的员工的薪水排名第三。

另一种表达方式是为此使用row_number()

select *
from (
    select 
        e.*, 
        row_number() over(order by salary desc) rn 
    from employee e
) t
where rn = 3

取决于您要如何处理重复项,dense_rank()也可能是一个选项。


0
投票
SELECT * FROM (SELECT EMP.ID,RANK() OVER (ORDER BY SALARY DESC) AS NOS FROM EMPLOYEE) T WHERE T.NOS=3

然后从此选择具有任何所需等级的那个。


0
投票

运行此查询时更容易理解:

select e1.*, 
       (select count(distinct e2.salary)
          from employee e2
          where e2.salary > e1.salary) as n
  from employee e1

这是我的示例表:

create table employee(salary) as (
  select * from table(sys.odcinumberlist(1500, 1200, 1400, 1500, 1100)));

所以我的输出是:

    SALARY          N
---------- ----------
      1500          0
      1200          2
      1400          1
      1500          0
      1100          3

您可以看到,子查询的每一行所计数的薪水均大于当前行中的薪水。例如,对于1400,有一个DISTINCT更高的薪水(1500)。 1500在我的表中出现了两次,但是distinct使得它被计数一次。所以1400是第二。

您的查询已将此计数移至where部分,并与所需值进行比较。我们必须减去一个,因为对于最高薪水没有更高的价值,对于第二薪水则没有一行,等等。

这是用于找到此类值的方法之一,较新的Oracle版本引入了分析函数(rank,row_number,densage_rank),从而无需为此目的使用子查询。它们更快,更高效。对于您的查询,dense_rank()将很有用。

© www.soinside.com 2019 - 2024. All rights reserved.