LeetCode 185. 部门工资前三高的所有员工 是一道经典的 SQL 窗口函数(Window Function) 题目。

📌 题目要求

有两张表:

Employee 表:
Column Name Type
id int

name varchar

salary int

departmentId int

Department 表:
Column Name Type
id int

name varchar

要求:找出 每个部门工资前三高 的所有员工(注意:并列排名也算,即可能返回超过 3 人)

输出格式:
Department Employee Salary

✅ 正确解法:使用 DENSE_RANK()

🔑 关键点
使用 DENSE_RANK() 而不是 ROW_NUMBER() 或 RANK()
DENSE_RANK():相同工资排名相同,且后续排名连续
例如:[100, 90, 90, 80] → 排名 [1, 2, 2, 3]
RANK():相同工资排名相同,但跳过后续排名
例如:[100, 90, 90, 80] → 排名 [1, 2, 2, 4] ❌(会漏掉第 3 名)
ROW_NUMBER():强制唯一排名 → 相同工资也会分先后 ❌

✅ 题目要求“工资前三高”,相同工资应视为同一排名,且都要保留。

💡 SQL 查询(MySQL 8.0+)

SELECT
d.name AS Department,
e.name AS Employee,
e.salary AS Salary
FROM (
SELECT
name,
salary,
departmentId,
DENSE_RANK() OVER (PARTITION BY departmentId ORDER BY salary DESC) AS rk
FROM Employee
) e
JOIN Department d ON e.departmentId = d.id
WHERE e.rk <= 3;

🔍 执行步骤解析

子查询 e:
按 departmentId 分组(PARTITION BY)
在每组内按 salary DESC 排序
用 DENSE_RANK() 计算每个员工在其部门的工资排名

JOIN Department:
获取部门名称

WHERE rk <= 3:
保留每个部门排名前 3 的员工(含并列)

🧪 示例验证

输入:
Employee
id name salary departmentId
1 Joe 85000 1

2 Henry 80000 2

3 Sam 60000 2

4 Max 90000 1

5 Janet 69000 1

6 Randy 85000 1

Department
id name
1 IT

2 Sales

子查询结果(IT 部门):
name salary departmentId rk
Max 90000 1 1

Joe 85000 1 2

Randy 85000 1 2

Janet 69000 1 3

→ 前三高:Max (1), Joe & Randy (2), Janet (3) → 共 4 人 ✅

最终输出:
Department Employee Salary
IT Max 90000

IT Joe 85000

IT Randy 85000

IT Janet 69000

Sales Henry 80000

Sales Sam 60000

✅ Sales 部门只有两人,全部返回。

⚠️ 兼容性说明

MySQL 8.0+ 支持窗口函数(DENSE_RANK())
如果使用 旧版 MySQL(<8.0),需用自连接或变量模拟,但 LeetCode 环境已支持窗口函数

❌ 常见错误写法

错误 1:使用 ROW_NUMBER()
– ❌ 相同工资会被强制排序,可能漏掉并列第三
ROW_NUMBER() OVER (PARTITION BY … ORDER BY salary DESC)

错误 2:使用 LIMIT(无法按部门分组限制)
– ❌ LIMIT 是全局的,不能 per department
SELECT … ORDER BY salary DESC LIMIT 3

错误 3:使用 RANK()
– ❌ 可能跳过排名,导致 rk=3 的记录被过滤
– 例如:[100, 90, 90, 80] → rk=[1,2,2,4],80 被排除
RANK() OVER (…)

✅ 总结
要点 说明
窗口函数 DENSE_RANK() 是本题核心

分区 PARTITION BY departmentId

排序 ORDER BY salary DESC

过滤 WHERE rk <= 3

连接 关联 Department 表获取部门名

💡 一句话答案:
用 DENSE_RANK() 按部门分组降序排名,取前 3 名即可。

此解法简洁、高效、符合题意,是 LeetCode 官方推荐做法。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐