LeetCode Database 176 第二高的薪水

1. 题目描述

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

1
2
3
4
5
6
7
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+

例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null

1
2
3
4
5
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+

2. 题解

2.1. MySQL 题解(ORDER BY + LIMIT)

一开始我想到先用ORDER BY排序,再LIMIT 1,1取第2个

1
2
3
SELECT Salary AS SecondHighestSalary
FROM Employee
ORDER BY Salary DESC LIMIT 1,1

提交出错。当表中只有一条记录,要求输出结果为null,但是我的输出为空字符串。

1
2
3
Input: {"headers": {"Employee": ["Id", "Salary"]}, "rows": {"Employee": [[1, 100]]}}
Output: {"headers":["SecondHighestSalary"],"values":[]}
Expected: {"headers":["SecondHighestSalary"],"values":[[null]]}

我感觉很奇怪,到MySQL做了一下测试,发现记录只有一条时,就是返回null。没办法,暂时认为是系统的BUG吧。于是我修改了一下SQL,在外面套了一层SELECT

1
2
SELECT (SELECT Salary FROM Employee 
ORDER BY Salary DESC LIMIT 1,1) AS SecondHighestSalary

提交还是出错,但是是新的错误,说明刚才的样例通过了。现在的错误是:表中有2条Salary相同的记录,要求返回null,但是我的输出的100。就是说,系统要求Salary的排序是经过去重的

1
2
3
输入 {"headers": {"Employee": ["Id", "Salary"]}, "rows": {"Employee": [[1, 100], [2, 100]]}}
输出 {"headers":["SecondHighestSalary"],"values":[[100]]}
预期结果 {"headers":["SecondHighestSalary"],"values":[[null]]}

将排序修改为去重排序,提交成功,以下是正确做法:

1
2
SELECT (SELECT DISTINCT Salary FROM Employee 
ORDER BY Salary DESC LIMIT 1,1) AS SecondHighestSalary

题解中,看到有的人使用了IFNULL(expr1, expr2),这个函数的作用是,如果expr1不为NULL,则返回expr1,否则返回expr2。他们是这样做的,显然这里使用的IFNULL是多余的,去掉就是上面的正确做法,还是对的

1
2
SELECT IFNULL((SELECT DISTINCT Salary FROM Employee 
ORDER BY Salary DESC LIMIT 1,1), NULL) AS SecondHighestSalary

2.2. MySQL 题解(MAX嵌套)

用两层MAX查询。第1次查出最大的Salary,第2次在去掉最大值的记录中,查询最大的Salary。使用MAX查询的好处是,已经是去重的结果,不需要使用DISTINCT

1
2
3
4
5
6
-- 形式1:MAX嵌套查询,使用"等号"
SELECT MAX(Salary) AS SecondHighestSalary FROM Employee
WHERE Salary != (SELECT MAX(Salary) FROM Employee)
-- 形式2:MAX嵌套查询,使用"小于号"
SELECT MAX(Salary) AS SecondHighestSalary FROM Employee
WHERE Salary < (SELECT MAX(Salary) FROM Employee)

第1次查询最大值也可以不用MAX,改为ORDER BY + LIMIT,但是实现的思路还是没有变化。但是你要知道,MAX的运行效率要比ORDER BY高,但是面试时可能会要求你给出多种解法,所以还是记录一下。

1
2
3
SELECT MAX(Salary) AS SecondHighestSalary FROM Employee
WHERE Salary != (SELECT Salary FROM Employee
ORDER BY Salary LIMIT 1)

panchaoxin wechat
关注我的公众号
支持一下