dense_rank()和max,找第N高薪水哪个更好(return没有结果则为null)

dense_rank() and max, which one is better to find Nth highest salary (return null if no result)

例如 N 是 2,我可以使用 densr_rank() 或 max 从员工 table.

中找到第二高的薪水
select max(salary) as SecondHighestSalary from employee 
where salary < (select max(salary) from employee) 

以上查询工作完美,条件是如果 table 中没有第二高的薪水,它 returns NULL。

但是我可以使用 dense_rank() 函数实现类似的结果,例如:

select e.salary as SecondHighestSalary 
from (
      select salary, dense_rank() OVER (order by salary desc) dr from employee) e
where dr = 2  

上面的查询工作正常,因为 table 中只有第二高的薪水,如果 table 有薪水 [300, null, null] 它返回 [null, null],我只需要结果集中的一个答案。我怎样才能做到这一点?

跟进问题:在这种情况下,哪个更好(就memory/processing时间而言) max 或 dense_rank ()?

这是一个非常有趣的问题。您尚未指定数据库。但是,如果我假设您在 salary 上有一个可由查询使用的索引(因此可能 salary desc 取决于数据库)。那么您的第一个查询可能会有很好的性能:

  • 使用索引获取匹配工资。
  • 开始扫描索引中小于最大值的值。
  • 将扫描短路,因为您会立即获得最大值。

我不保证所有数据库都会生成此计划,但在这种情况下,两次索引查找通常会比 dense_rank() 快。

当然,像这样的问题,你应该测试你的数据和你的数据库。这真是正确答案。

您使用 max 的查询仅适用于 N = 2,因此这是一个糟糕的解决方案,但就性能而言,它应该比使用 dense_rank.

的第二个查询更好

我建议另一种方法:仅获取按 salary 降序排列的前 N ​​行。然后,从这个结果中得到最低的薪水。

如果您在 salary 列上有索引,那么获取 N 行应该快如闪电。然后“只有”N行,获取最后一条记录应该也很快。

所以查询应该看起来像(对于 SQL 服务器):

SELECT TOP 1 * FROM (
    SELECT TOP N * FROM SalaryTable ORDER BY salary DESC
) ORDER BY salary;

对于那些具有 LIMIT N 而不是 SELECT TOP N 的 RDBMS:

SELECT * FROM (
    SELECT * FROM SalaryTable ORDER BY salary DESC LIMIT N
) ORDER BY salary LIMIT 1;