PERCENT_RANK是返回0到1间相对排名的窗口函数,公式为(rank−1)/(total_rows−1);RANK跳号(如1,1,3),DENSE_RANK不跳号(如1,1,2),二者均返回整数排名且处理并列方式不同。

PERCENT_RANK 是什么,它和 RANK、DENSE_RANK 有什么区别
PERCENT_RANK 返回的是当前行在分组内的相对排名位置(0 到 1 之间的浮点数),计算公式是:(rank - 1) / (total_rows - 1)。注意:它基于 RANK() 的排名结果,不是按值插值,也不处理并列——并列时共享相同 RANK,因此也共享相同 PERCENT_RANK。
-
RANK():跳过后续名次(如 1,1,3) -
DENSE_RANK():不跳过(如 1,1,2) -
PERCENT_RANK():只依赖RANK,且分母固定为组内总行数减 1
最易踩的坑是误以为它“按数值线性插值”,比如成绩 85 分在 [80,90] 区间就给 50%,实际完全不是——它只看排序位置。
基本用法:必须搭配 OVER(),且 ORDER BY 不可省略
PERCENT_RANK() 是窗口函数,必须写在 OVER() 子句中,且 ORDER BY 是强制项(没有排序就没有“排位”概念):
SELECT score,
PERCENT_RANK() OVER (ORDER BY score) AS pct_rank
FROM exam_scores;
- 如果漏掉
ORDER BY,多数数据库(PostgreSQL、SQL Server、Oracle)直接报错:ERROR: window function PERCENT_RANK requires an ORDER BY clause -
PARTITION BY可选,但一旦使用,PERCENT_RANK就在每个分区独立计算(分母变为该分区行数 − 1)
第一个和最后一个值的 PERCENT_RANK 固定为 0 和 1
这是由定义决定的:最小值的 RANK 是 1 → (1−1)/(n−1) = 0;最大值的 RANK 是 n → (n−1)/(n−1) = 1。
- 即使数据只有 1 行,
PERCENT_RANK()仍返回 0(因为n=1→ 分母为 0?不,SQL 标准规定此时结果为 0) - 若有重复极值(如多个最低分),它们都得 0;多个最高分都得 1
- 这和
CUME_DIST()不同——后者首行为1/n,末行为 1
实际查数据时,小数精度和 NULL 处理要特别小心
PERCENT_RANK 默认返回 double precision 或 numeric 类型,显示可能带多位小数。业务上常需 ROUND(..., 4) 控制精度。
-
NULL值默认排在最前(NULLS FIRST),所以如果ORDER BY score里没显式声明,NULL行会得到PERCENT_RANK = 0,容易误导 - 正确做法是明确控制:
ORDER BY score NULLS LAST(PostgreSQL/Oracle)或用CASE过滤 - MySQL 8.0+ 支持
PERCENT_RANK,但旧版不支持;SQLite 不支持;SQL Server 和 Oracle 全支持
真正麻烦的不是语法,而是看到结果里一堆 0.0000 和 1.0000 时,没意识到这背后是并列极值或单行分区导致的必然现象。










