在业务报表里,我们经常需要按某个维度分组,然后取出每组中数值排在前一半也就是中位线以上的记录。传统写法要先算每组中位数再关联原表,逻辑繁琐。使用PERCENT_RANK窗口函数可以直接在查询中生成组内百分比排名,再过滤即可。

什么是PERCENT_RANK
PERCENT_RANK是SQL标准里的窗口函数,它返回当前行在分区内的相对排名,计算结果从0到1。第一行是0,最后一行是1,中间按行数线性分布。公式为:(组内排名 - 1) / (组内总行数 - 1)。
基本语法结构
配合PARTITION BY实现分组,ORDER BY决定组内排序方向。示例如下:
SELECT
dept_id,
emp_name,
salary,
PERCENT_RANK() OVER (
PARTITION BY dept_id
ORDER BY salary ASC
) AS pr
FROM employee;
上面语句按部门分组,计算每个员工薪资在部门内的百分比排名。若某行pr大于0.5,说明它排在部门中位线以上。
筛选中位线以上记录
把上述查询作为子查询或CTE,加上WHERE条件就能拿到结果:
WITH ranked AS (
SELECT
dept_id,
emp_name,
salary,
PERCENT_RANK() OVER (
PARTITION BY dept_id
ORDER BY salary ASC
) AS pr
FROM employee
)
SELECT
dept_id,
emp_name,
salary,
pr
FROM ranked
WHERE pr > 0.5
ORDER BY dept_id, salary DESC;
处理边界情况
- 当组内只有一行时,PERCENT_RANK返回0,不会被选中,符合预期。
- 若组内行数为偶数,正好一半行的pr等于0.5,用大于号可排除恰好在中位线上的行。
- 如需包含中位线,可改为 pr >= 0.5。
与其它函数对比
| 函数 | 返回值范围 | 是否含分组 |
|---|---|---|
| PERCENT_RANK | 0到1 | 支持PARTITION BY |
| CUME_DIST | 大于0到1 | 支持PARTITION BY |
| RANK | 从1开始整数 | 支持PARTITION BY |
相比先聚合再JOIN,PERCENT_RANK只需一次扫描,代码更简洁,性能也更好。在MySQL 8.0、PostgreSQL、SQL Server等主流数据库均可直接使用。
SQLPERCENT_RANK分组查询修改时间:2026-07-28 04:48:24