【发布时间】:2011-01-30 06:27:09
【问题描述】:
是否有任何预定义的函数或方法可用于从员工表中获取第二高的薪水?
【问题讨论】:
是否有任何预定义的函数或方法可用于从员工表中获取第二高的薪水?
【问题讨论】:
试试这个:
SELECT * FROM employee emp WHERE 2=(SELECT COUNT(*) FROM employee WHERE
salary >= emp.salary);
【讨论】:
在 Oracle 中,您将使用这样的查询来返回分页结果(行 M 到 N):
SELECT NAME, salary
FROM (SELECT NAME, salary, ROWNUM r
FROM (SELECT NAME, salary
FROM employee
ORDER BY salary DESC
)
WHERE ROWNUM <= :N
)
WHERE r >= :M
或者,您可以使用分析:
SELECT NAME, salary
FROM (SELECT NAME, salary, row_number() over (ORDER BY salary DESC) n
FROM employee)
WHERE n BETWEEN :M AND :N
【讨论】:
执行此操作的方法是使用 Oracle 的分析功能。您的特定场景只是我在another thread 中提供的解决方案的一种变体。
如果您只想选择第二高的薪水,那么 DENSE_RANK()、RANK() 和 ROW_NUMBER() 中的任何一个都可以解决问题:
SQL> select * from
2 ( select sal
3 , rank() over (order by sal desc) as rnk
4 from
5 ( select distinct sal
6 from emp )
7 )
8 where rnk = 2
9 /
SAL RNK
---------- ----------
3000 2
SQL>
但是,如果您要选择附加信息,例如薪水第二高的员工的姓名,您选择的功能会影响结果。选择一个而不是另一个的主要原因是出现平局时会发生什么。
如果您使用 ROW_NUMBER(),它将返回按薪水排序的第二名员工:如果有两名员工并列最高薪水怎么办?如果有两名员工并列第二高的薪水怎么办?如果您使用 RANK() 并且有两个员工并列第一高薪,那么将有 no 记录 RANK = 2。
我建议 DENSE_RANK() 通常是在这些情况下选择最安全的函数,但它确实取决于特定的业务需求。
【讨论】:
如果你想从表中找出n个最高的薪水,你可以这样:
select min(sal)from (select distinct sal from emp order by sal desc) where rownum<=n;
其中 n 是 1,2,3, ..., n
从表格中找出最高工资是一个非常简单的过程。
【讨论】:
使用Oracle DB 12c 处理Top-N 查询更容易,它引入了这样的语法:
[ OFFSET offset { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
{ ROW | ROWS } { ONLY | WITH TIES } ]
用于ORDER BY 列表之后的查询。
在这种情况下考虑使用:
select *
from emp
order by sal desc
offset 1 rows fetch next 1 rows only
其中使用offset 是可选的,从语法中已经可以看出,并指出fetch 子句的起点将是offset + 1。
一个特殊情况是ties,这意味着多行匹配第 N 行的值(这里我们需要第 2 行)。如果第二名的薪水相同的人不止一个,那么我们需要将only关键字替换为with ties以全部返回:
select *
from emp
order by sal desc
offset 1 rows fetch next 1 rows with ties
【讨论】: