关于PERCENT_RANK函数ASC/DESC排序结果的正确性问询
关于PERCENT_RANK排序结果正确性的疑问
我有一张包含5行数据的emp_sal表,需要解答以下两个问题:
- a) 薪资高于1500的员工占比是多少?
- b) 薪资低于1500的员工占比是多少?
使用不同排序方式的PERCENT_RANK()查询得到了不同结果:
- QUERY_A(升序排序):25%的员工薪资低于1500,75%的员工薪资高于1500
- QUERY_B(降序排序):50%的员工薪资高于1500,50%的员工薪资低于1500
请问哪一个查询能正确解答上述两个问题?
具体查询语句及结果
QUERY_A(升序排序)
select salary, round( percent_rank() over(order by salary ASC), 2 ) * 100 as pct_asc from emp_sal;
查询结果:
| SALARY | PCT_ASC |
|---|---|
| 1000 | 0 |
| 1500 | 25 |
| 1500 | 25 |
| 2000 | 75 |
| 3000 | 100 |
QUERY_B(降序排序)
select salary, round( percent_rank() over(order by salary DESC), 2 ) * 100 as pct_desc from emp_sal;
查询结果:
| SALARY | PCT_DESC |
|---|---|
| 3000 | 0 |
| 2000 | 25 |
| 1500 | 50 |
| 1500 | 50 |
| 1000 | 100 |
分析与结论
首先明确PERCENT_RANK()的计算公式:(当前行的排名 - 1) / (总行数 - 1),其中排名基于指定的排序规则,相同薪资的行共享同一排名。
实际员工薪资分布
表中5个员工的薪资为:1000、1500、1500、2000、3000。实际的绝对占比为:
- 薪资低于1500:1人,占比
1/5 = 20% - 薪资高于1500:2人,占比
2/5 = 40% - 薪资等于1500:2人,占比
2/5 = 40%
对两个查询结果的解读
QUERY_A(升序)
PCT_ASC表示:升序排序下,薪资小于当前行的员工占总行数-1的比例。- 薪资1500对应的
25%,是相对排名比例(1/(5-1)=25%),代表有25%的员工薪资低于1500,但这不是绝对的行数占比。 - 若将“高于1500”放宽为“不低于1500”,则
100%-25%=75%是相对排名中不低于1500的比例,但不符合问题中“高于”的严格定义。
QUERY_B(降序)
PCT_DESC表示:降序排序下,薪资大于当前行的员工占总行数-1的比例。- 薪资1500对应的
50%,是相对排名比例(2/(5-1)=50%),代表有50%的员工薪资高于1500,同样不是绝对的行数占比。 - 若将“低于1500”放宽为“不高于1500”,则
100%-50%=50%是相对排名中不高于1500的比例,也不符合问题中“低于”的严格定义。
结论
如果需求是获取绝对的员工占比,两个查询的结果都不准确,应该直接统计行数计算:
-- 计算薪资低于1500的绝对占比 select round(count(case when salary < 1500 then 1 end) * 100.0 / count(*), 2) as pct_below from emp_sal; -- 计算薪资高于1500的绝对占比 select round(count(case when salary > 1500 then 1 end) * 100.0 / count(*), 2) as pct_above from emp_sal;
如果需求是基于PERCENT_RANK的相对排名比例:
- QUERY_A准确回答了“相对排名中薪资低于1500的员工比例”(25%)
- QUERY_B准确回答了“相对排名中薪资高于1500的员工比例”(50%)
不存在单个查询能同时正确解答两个严格定义下的问题,除非放宽“高于/低于”的定义为“不低于/不高于”,但仍无法同时满足两个问题的原始要求。
内容的提问来源于stack exchange,提问作者askren
相关产品推荐
相关产品推荐

