首页/数据/SQL 速查/PERCENT_RANK 相对排名
聚合与窗口函数54 条

PERCENT_RANK 相对排名

相对排名 = (名次 - 1) / (总行数 - 1),取值 0 到 1;用于“排在前面百分之多少”。

SQL 速查数据更新于 2026-10-13

相对排名怎么算

PERCENT_RANK() 给出相对排名,公式是(名次减一)除以(总行数减一),取值落在 0 到 1 之间。它回答的是「排在前面百分之多少」,常用于分位定位与分层,与按行数等分的 NTILE 是两回事。

基本信息

取值范围0 到 1
边界分区内数值居首者为 0,居末者为 1
公式(名次 - 1) / (总行数 - 1)
对比CUME_DIST 表示小于等于当前值的比例,并列行结果不同
适用平台MySQL 8.0+ 与 PostgreSQL

典型使用场景

  • 判断某个值处在什么百分位
  • 按相对排名给用户分层
  • 报表里标注「超过了多少比例的用户」
  • 与 CUME_DIST 对比理解并列行差异
  • 用于分位数的近似定位

示例

示例
-- 相对排名:数值越小说明越靠前
SELECT name, score,
       ROUND(PERCENT_RANK() OVER (ORDER BY score DESC), 4) AS pr
FROM exams;

-- 分组内计算:每个班级各自的相对排名
SELECT class_id, name, score,
       ROUND(PERCENT_RANK() OVER (PARTITION BY class_id ORDER BY score DESC), 4) AS pr
FROM exams;

-- 与 CUME_DIST 对比:并列行的结果不同
SELECT name, score,
       PERCENT_RANK() OVER (ORDER BY score DESC) AS pr,
       CUME_DIST()    OVER (ORDER BY score DESC) AS cd
FROM exams;

与相邻函数对照

函数取值并列行表现
PERCENT_RANK0 到 1并列行取值相同
CUME_DIST大于 0 到 1表示小于等于当前值的比例
RANK整数名次并列跳号
DENSE_RANK整数名次并列不跳号
NTILE桶号按行数等频分桶
分区只有一行时 PERCENT_RANK 返回 0:公式分母为零,数据库按约定返回 0,统计口径要单独说明。
「按行数等分」用 NTILE,「按数值比例定位」用 PERCENT_RANK,两者不可互换:前者的桶大小由行数决定,后者由名次比例决定。
报表里常把它换算成「超过多少比例的用户」:展示时用 1 减去相对排名更符合直觉,直接给出原值容易让人读反。
分组维度决定含义:按整体算与按分组算得到的相对排名完全不同,报表里要写清是全局排名还是组内排名。
它与分位数搭配使用效果更好:相对排名给出位置,分位数给出取值,两者一起看才能说清分布形态。

易错点

  • 分区只有 1 行时 PERCENT_RANK 为 0:统计口径要单独说明,否则会误判为排名最前
  • PERCENT_RANK 与 NTILE 互换使用:前者按名次比例,后者按行数分桶,结果完全不同
  • 把它当百分比直接展示:返回值是 0 到 1 的小数,展示前要换算
  • 忽略并列值:并列行拿到相同排名,按它筛「前 10%」可能多出若干行
  • 排序键不唯一导致结果不稳定:需要可复现的分层结果就补一个唯一排序键

数据来源与参考

  • MySQL 8.0 Reference Manual · PERCENT_RANK
  • PostgreSQL Documentation · Window Functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌