我试图理解下面的查询,它是如何工作的。
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
也需要与内部计数匹配。内部计数的操作方式。
谁能解释它是如何工作的..?
子查询是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()
也可能是一个选项。
SELECT * FROM (SELECT EMP.ID,RANK() OVER (ORDER BY SALARY DESC) AS NOS FROM EMPLOYEE) T WHERE T.NOS=3
然后从此选择具有任何所需等级的那个。
运行此查询时更容易理解:
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()
将很有用。