SQL 中排名与去重的经典题

SQL 中排名与去重的经典题 ### 核心知识点解析这道题是 SQL 中**排名与去重**的经典题主要考察以下几个关键知识点***#### 1. 去重DISTINCT* 题目要求 “**第二高的不同薪水**”所以必须先对 salary 字段去重避免重复值干扰排名。* 语法示例sqlSELECT DISTINCT salary FROM Employee#### 2. 排序与分页ORDER BY LIMIT* 要找到 “第二高”需要先按薪水**降序**排列再取第 2 条记录。* LIMIT 语法LIMIT offset, count其中 offset 是偏移量从 0 开始count 是返回条数。* 取第 2 高LIMIT 1, 1跳过 1 条取 1 条。* 语法示例sqlSELECT DISTINCT salaryFROM EmployeeORDER BY salary DESCLIMIT 1, 1#### 3. 处理空结果IFNULL / MAX / 子查询* 当不存在第二高薪水时如只有 1 条记录或所有记录薪水相同需要返回 null。* 方法 1使用 IFNULL 包裹子查询MySQL 语法sqlSELECT IFNULL((SELECT DISTINCT salaryFROM EmployeeORDER BY salary DESCLIMIT 1, 1),NULL) AS SecondHighestSalary* 方法 2使用 MAX 函数当子查询无结果时MAX 会返回 nullsqlSELECT MAX(salary) AS SecondHighestSalaryFROM (SELECT DISTINCT salaryFROM EmployeeORDER BY salary DESCLIMIT 1, 1) AS temp#### 4. 窗口函数进阶RANK / DENSE\_RANK* 更通用的解法是使用窗口函数适合处理 “第 N 高” 的场景sqlSELECT DISTINCT salary AS SecondHighestSalaryFROM (SELECT salary,DENSE_RANK() OVER (ORDER BY salary DESC) AS rnkFROM Employee) AS tempWHERE rnk 2* DENSE_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 问题。