如果我有关系:员工(身份证,工资)。什么是最简单的SQL查询来选择薪水第二高的人的ID。
我知道如何使用以下方式选择最高薪水:
SELECT MAX(salary)
FROM employee
WHERE salary < (SELECT MAX(salary)
FROM employee);
但是如何选择该人的身份证,并仅显示薪水第二高的人的身份证(不使用LIMIT)。
答案 0 :(得分:3)
最佳答案取决于薪水指数的存在。我已经设置了sqlfiddle,在表格中加载了100k行。
使用索引,我的答案是:
SELECT * FROM employee ORDER BY salary DESC LIMIT 1 OFFSET 1;
这是最简单,最简洁,最干净的一种。它也是最快的,40μs,因为它使用索引扫描向后。但是,如果第二个位置存在搭配,则只会返回一行。
仍然使用索引,在子查询中使用max()的上述三个查询紧随其后。鲍勃贾维斯得分100μs。
不幸的是,当postgres扫描整个索引时,Gordon的窗口函数遇到了障碍(好吧,至少它没有排序):
Subquery Scan on e (cost=0.29..7518.27 rows=500 width=20) (actual time=0.042..137.810 rows=1 loops=1)
Filter: (e.seqnum = 2)
Rows Removed by Filter: 99999
-> WindowAgg (cost=0.29..6268.27 rows=100000 width=20) (actual time=0.029..121.445 rows=100000 loops=1)
-> Index Scan Backward using emps_sal on employee e_1 (cost=0.29..4768.27 rows=100000 width=12)
(actual time=0.022..54.861 rows=100000 loops=1)
这需要137毫秒,这是很长的。我认为postgres的根本原因是将“seqnum = 2”视为任何其他WHERE表达式,因此没有意识到它可能在第二行之后停止。我们可以通过添加“LIMIT 1”来轻推它,在这种情况下它会在第二行之后停止,并且只需要70μs,所以它非常快。
现在,没有索引......
我对ORDER BY的查询做了一个排序,但它是postgres'辉煌的top-n heapsort,速度很快:34ms。
Gordon't window函数完全排序,需要108ms。
Bob的查询没有排序,但它会扫描表3次:84 ms。
答案 1 :(得分:0)
我会使用row_number()
或rank()
,具体取决于第二高薪的含义:
SELECT e.*
FROM (SELECT e.*, RANK() OVER (ORDER BY salary DESC) as seqnum
FROM employee e
) e
WHERE seqnum = 2;
如果你想使用你的查询 - 这看起来更复杂 - 你可以使用子查询:
SELECT e.*
FROM employee e
WHERE e.salary = (SELECT MAX(e2.salary)
FROM employee e2
WHERE e2.salary < (SELECT MAX(e3.salary)
FROM employee e3
)
);
很高兴看到SQL在过去30年中取得了一些进展。
答案 2 :(得分:0)
SELECT *
FROM employee
WHERE salary = (
SELECT max(salary)
FROM employee
WHERE salary != (
SELECT max(salary)
FROM employee
)
);
答案 3 :(得分:0)
SELECT ID
FROM EMPLOYEE
WHERE SALARY = (SELECT MAX(salary) AS SECOND_HIGHEST_SALARY
FROM employee
WHERE salary < (SELECT MAX(salary) AS HIGHEST_SALARY
FROM employee)
这将为您提供薪水第二高的所有员工的ID。如果您只希望一名员工在外部查询中使用SELECT MIN(ID)
。