什么是简单的SQL查询来选择具有第二高工资的人员的ID

时间:2017-08-20 13:05:14

标签: sql postgresql

如果我有关系:员工(身份证,工资)。什么是最简单的SQL查询来选择薪水第二高的人的ID。

我知道如何使用以下方式选择最高薪水:

SELECT MAX(salary)
FROM employee
WHERE salary < (SELECT MAX(salary)
FROM employee);

但是如何选择该人的身份证,并仅显示薪水第二高的人的身份证(不使用LIMIT)。

4 个答案:

答案 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)