1. 题目描述
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
1 | +----+--------+ |
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。
1 | +---------------------+ |
2. 题解
2.1. MySQL 题解(ORDER BY + LIMIT)
一开始我想到先用ORDER BY排序,再LIMIT 1,1取第2个
1 | SELECT Salary AS SecondHighestSalary |
提交出错。当表中只有一条记录,要求输出结果为null,但是我的输出为空字符串。
1 | Input: {"headers": {"Employee": ["Id", "Salary"]}, "rows": {"Employee": [[1, 100]]}} |
我感觉很奇怪,到MySQL做了一下测试,发现记录只有一条时,就是返回null。没办法,暂时认为是系统的BUG吧。于是我修改了一下SQL,在外面套了一层SELECT
1 | SELECT (SELECT Salary FROM Employee |
提交还是出错,但是是新的错误,说明刚才的样例通过了。现在的错误是:表中有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
2SELECT (SELECT DISTINCT Salary FROM Employee
ORDER BY Salary DESC LIMIT 1,1) AS SecondHighestSalary
题解中,看到有的人使用了IFNULL(expr1, expr2),这个函数的作用是,如果expr1不为NULL,则返回expr1,否则返回expr2。他们是这样做的,显然这里使用的IFNULL是多余的,去掉就是上面的正确做法,还是对的1
2SELECT 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查询的好处是,已经是去重的结果,不需要使用DISTINCT1
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
3SELECT MAX(Salary) AS SecondHighestSalary FROM Employee
WHERE Salary != (SELECT Salary FROM Employee
ORDER BY Salary LIMIT 1)