订阅更新

第二高的薪水:没有第二名时怎么返回 NULL

SQL 实战 123 题 · 第 2 题 简单 约 2 分钟读完

LeetCode 176 · 去重排序、LIMIT OFFSET、空结果转 NULL

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

我先对薪水去重后降序,用 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。
刷题进度保存在当前浏览器