第二高的薪水:没有第二名时怎么返回 NULL
LeetCode 176 · 去重排序、LIMIT OFFSET、空结果转 NULL
面试怎么回答
我先对薪水去重后降序,用 LIMIT 1 OFFSET 1 取第二档;为了在没有第二高时返回 NULL 而不是空集,把它包成外层 SELECT 里的标量子查询,再用 IFNULL 兜底。也可以用 DENSE_RANK 取 rk = 2,相同薪水排名相同,语义和「第二高的薪水档位」一致。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
从员工表里找出第二高的薪水。同样的薪水只算一个档位;如果公司里只有一个薪水档位,结果要返回一行 NULL,而不是空结果。
表结构
- Employee:Id(主键)、Salary
思路
先对薪水去重,再按降序跳过第一名取一条,就是第二高。难点在边界:当不存在第二名时,LIMIT 1 OFFSET 1 返回的是空集,而题目要一行 NULL。把这个查询包成标量子查询放在外层 SELECT 里,空结果会自然变成 NULL,再用 IFNULL 兜底就更明确。
参考解法
SELECT
IFNULL(
(SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET 1),
NULL) AS SecondHighestSalary
另一种写法:用 DENSE_RANK 取排名为 2 的薪水,同样外面包一层保证空时返回 NULL
SELECT (
SELECT DISTINCT Salary
FROM (SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS rk FROM Employee) t
WHERE rk = 2
) AS SecondHighestSalary
易错点
- 忘了 DISTINCT:薪水 300、300、200 时,不去重会把 300 当成第二高。
- 直接写
SELECT ... LIMIT 1 OFFSET 1不包子查询,没有第二名时返回空集而不是 NULL。