【问题标题】:Nth salary in SQLSQL中的第N个薪水
【发布时间】:2020-06-04 16:15:09
【问题描述】:

我正在尝试了解以下查询,它是如何工作的。

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 也需要与内部计数匹配。内部计数是如何运行的。

任何人都可以解释它的工作原理吗?

【问题讨论】:

  • DISTINCT 不是函数。跳过那些多余的括号以编写更清晰的代码,即只需执行SELECT COUNT(DISTINCT Emp2.Salary)
  • 我会使用子查询来返回第三大不同的薪水。
  • 可能是接受答案的idsa。

标签: sql oracle subquery greatest-n-per-group


【解决方案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() 也可能是一个选项。

【讨论】:

  • 那么这样说是否正确,在这种情况下,首先运行外部查询,然后运行内部查询..?理想情况下,内部查询首先运行。
  • @Maria:确实如此。子查询引用来自外部查询的列,因此它不可能先执行。
  • 我可能会使用dense_rank() 而不是row_number()
  • @a_horse_with_no_name:OP 并没有真正说明他们想要如何处理重复项,所以我选择了row_number()。我编辑了我的答案,提到了dense_rank()
【解决方案2】:
SELECT * FROM (SELECT EMP.ID,RANK() OVER (ORDER BY SALARY DESC) AS NOS FROM EMPLOYEE) T WHERE T.NOS=3

然后从中选择具有任何所需等级的人。

【讨论】:

    【解决方案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、dense_rank),从而无需为此目的使用子查询。它们更快、更高效。对于您的查询dense_rank() 会很有用。

    【讨论】:

      猜你喜欢
      • 2015-03-09
      • 2013-12-04
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      相关资源
      最近更新 更多