🔍 核心知识点解析
这道题是 SQL 中排名与去重的经典题,主要考察以下几个关键知识点:
1. 去重(DISTINCT)
-
题目要求 “第二高的不同薪水”,所以必须先对
salary字段去重,避免重复值干扰排名。 -
语法示例:
sql
SELECT DISTINCT salary FROM Employee
2. 排序与分页(ORDER BY + LIMIT)
-
要找到 “第二高”,需要先按薪水降序排列,再取第 2 条记录。
-
LIMIT语法:LIMIT offset, count,其中offset是偏移量(从 0 开始),count是返回条数。 -
取第 2 高:
LIMIT 1, 1(跳过 1 条,取 1 条)。 -
语法示例:
sql
SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 1, 1
3. 处理空结果(IFNULL / MAX / 子查询)
-
当不存在第二高薪水时(如只有 1 条记录或所有记录薪水相同),需要返回
null。 -
方法 1:使用
IFNULL包裹子查询(MySQL 语法):sql
SELECT IFNULL( (SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 1, 1), NULL ) AS SecondHighestSalary -
方法 2:使用
MAX函数,当子查询无结果时,MAX会返回null:sql
SELECT MAX(salary) AS SecondHighestSalary FROM ( SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 1, 1 ) AS temp
4. 窗口函数进阶(RANK / DENSE_RANK)
-
更通用的解法是使用窗口函数,适合处理 “第 N 高” 的场景:
sql
SELECT DISTINCT salary AS SecondHighestSalary FROM ( SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk FROM Employee ) AS temp WHERE rnk = 2DENSE_RANK():并列排名时不会跳过序号(如 300、200、200,排名为 1、2、2)。RANK():并列排名时会跳过序号(如 300、200、200,排名为 1、2、2、4)。
💡 易错点提醒
- ❌ 忘记去重:直接
ORDER BY salary DESC LIMIT 1,1会把重复薪水算成多条,导致排名错误。 - ❌ 不处理空结果:当只有 1 条记录时,子查询会返回空集,外层查询需要显式返回
null。 - ✅ 优先用
DISTINCT+LIMIT解决基础场景,窗口函数适合更复杂的排名需求。
📌 总结
这道题的本质是理解 “去重 → 排序 → 取第 N 条 → 处理空结果” 的完整流程。掌握了 DISTINCT、LIMIT 和 IFNULL/MAX,就能解决绝大多数 “第 N 高” 的 SQL 问题。