percent_rank()可精准定位各部门前10%员工:它按部门分组、薪资降序计算0~1相对排名,pct_rank
用 PERCENT_RANK() 窗口函数定位前10%员工
PERCENT_RANK()是最直接的工具:它为每个员工在部门内按薪资排序后,计算其相对排名(范围是 0 到 1,最高薪者为 0,最低薪者接近 1)。注意它不是“前 N 名”,而是按比例划分——所以PERCENT_RANK() 才对应前 10%。常见错误是误用
ROW_NUMBER()或RANK():它们返回整数序号,无法直接表达“10%”这个比例概念;强行用ROW_NUMBER() ) 0.1还得先聚合再 JOIN,逻辑绕且易出错。使用时必须搭配
PARTITION BY department和ORDER BY salary DESC,否则就变成全表排名,失去“每个部门”的前提。SELECT department, salary, PERCENT_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS pct_rank FROM employees;过滤并计算部门内前10%的平均薪资
关键在于:不能先算全局平均再过滤,也不能在子查询里漏掉
PARTITION BY。正确做法是把PERCENT_RANK()放在子查询或 CTE 中生成排名,外层只对pct_rank 的行求平均。
PERCENT_RANK()对相同薪资的员工会给出相同排名值(比如两个并列第1名,都得到 0.0),这符合业务直觉(同薪同待遇)- 若某部门只有 3 人,
PERCENT_RANK()结果为 0.0、0.5、1.0,那么只能选中 1 人(即最高薪者)——这是合理行为,不是 bug- 某些旧版 MySQL(
WITH ranked AS ( SELECT department, salary, PERCENT_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS pct_rank FROM employees ) SELECT department, ROUND(AVG(salary), 2) AS avg_top_10pct_salary FROM ranked WHERE pct_rank <h3>替代方案:用 NTILE(10) 分十分位但要注意陷阱</h3><p><code>NTILE(10)</code> 把每部门员工平均分成 10 组(编号 1–10),理论上第 1 组就是前 10%。但它强制“均分”,当部门人数不能被 10 整除时,低编号组会略多几人(例如 13 人会被分作 2,2,1,1,…),导致实际占比可能达 15% 或更高。</p>
- 不推荐用于精确的“前 10%”场景,更适合“大致分层”
NTILE()的分组边界不可控,相同薪资可能被拆到不同组,破坏一致性- 如果坚持用,必须加
ORDER BY salary DESC, employee_id避免非确定性分组真正要严格按比例截断,
PERCENT_RANK()是唯一可靠选择。别被“NTILE 看起来更直观”带偏——它的设计目标是分桶,不是百分位筛选。











