用row_number()可获取每部门最高薪员工,但并列时只返回一行;需全返回则改用rank();mysql 5.7以下需用子查询;注意null/空部门过滤及业务定义对齐。

用窗口函数 ROW_NUMBER() 获取每个部门最高薪员工
直接用 GROUP BY 会丢失员工姓名等非聚合字段,必须借助窗口函数。核心思路是按部门分组、按薪资降序排序,取每组第一行。
-
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC)为每个部门内员工按薪资从高到低编号 - 外层筛选
rn = 1即可拿到每个部门薪资最高的那条记录(注意:有并列时只取一个) - 如果存在多人同为最高薪且都要返回,改用
RANK()或DENSE_RANK(),否则ROW_NUMBER()会随机选一个
处理薪资并列情况:改用 RANK() 而不是 ROW_NUMBER()
当某部门有多个员工薪资相同且都是最高时,ROW_NUMBER() 只返回一行,而业务常要求全返回——这时必须换函数。
-
RANK() OVER (PARTITION BY department ORDER BY salary DESC)对相同薪资赋予相同排名,后续排名跳号(如 1,1,3) - 筛选条件改为
rk = 1,就能把所有并列最高薪员工都查出来 - 数据库兼容性没问题:
RANK()在 PostgreSQL、MySQL 8.0+、SQL Server、Oracle 中都支持
MySQL 5.7 或更老版本无法用窗口函数?用关联子查询兜底
老版本 MySQL 不支持窗口函数,只能靠自连接或相关子查询,性能较差但可行。
一款AI工具,主要用于将编码任务调度到本地 OpenAI Codex CLI,支持后台执行、状态轮询以及可交互式回答的澄清问题。适用于 OpenClaw 需要……,适合需要提升相关任务效率的用户。
- 写法示例:
SELECT t1.* FROM employees t1 WHERE salary = (SELECT MAX(salary) FROM employees t2 WHERE t2.department = t1.department) - 注意:如果某部门有多人同为最高薪,该写法天然支持全部返回,无需额外处理
- 缺点明显:子查询对大表很慢,且不能避免
MAX()和JOIN带来的重复扫描;有索引((department, salary))能缓解但不根治
别漏掉 NULL 或空部门数据的边界情况
实际数据里 department 字段可能为 NULL,或者存在空字符串,这些会被归为同一组,容易误统计。
- 加过滤条件:
WHERE department IS NOT NULL AND department != '',避免脏数据干扰结果 - 若需单独展示“部门未填”的最高薪员工,应显式用
GROUP BY COALESCE(department, 'UNKNOWN')或类似逻辑,而不是依赖默认分组行为 - 某些数据库(如 PostgreSQL)中
NULL在PARTITION BY时会被单独分组;MySQL 8.0 则把所有NULL归为一组——行为不一致,务必验证
真实场景里最麻烦的往往不是语法,而是“最高薪”定义本身:是否包含奖金?是否去重后取最大?有没有生效日期约束?这些得跟业务方对齐,光写对 SQL 不等于结果正确。










