使用NTILE计算百分位数?

时间:2012-03-22 19:44:17

标签: sql-server sql-server-2008 tsql

需要计算每个学生的百分位数(第1至第99百分位数)并获得单项考试的分数。

我对NTILE的msdn定义感到有些困惑,因为它没有明确提到百分等级。我需要某种保证,NTILE是用于计算百分等级的正确关键字。

declare @temp table
(
  StudentId int,
  Score int
)
insert into @temp
select 1, 20
union
select 2, 25
.....

select NTILE(100) OVER (order by Score) PercentileRank
from @temp

对我来说看起来不错,但这是计算百分等级的正确方法吗?

5 个答案:

答案 0 :(得分:3)

NTILE绝对与百分位数不同。 NTILE简单地用提供的数字均匀地划分一组数据(如上面的RoyiNamir所述)。如果你绘制两个函数的结果,NTILE将是从1到n的完美线性线,而百分位数[通常]会根据你的数据有一些曲线。

百分位数比简单地将其除以N要复杂得多。它然后取每行的数字并计算它所在的分布中的位置,必要时进行插值(这是非常占用CPU的)。我有一张525,000行的Excel工作表,它在我的8核机器的CPU上以100%的速度占据15-20分钟,只是为了找出单列的PERCENTRANK函数。

本文更好地解释了百分比等级以及如何在SQL中执行此操作:

http://sqlmag.com/t-sql/calculate-percentiles

答案 1 :(得分:2)

想到这一点的一种方法是,“分数低于这一分的学生百分比。”

以下是使用RANK()在SQL Server中获取此类百分位数的一种方法:

select *
    , (rank() over (order by Score) - 1.0) / (select count(*) from @temp) * 100 as PercentileRank
from @temp

请注意,除非您向上舍入,否则总是小于100%,并且对于最低值,您将始终获得0%。这并不一定将中值设为50%,也不会像某些百分位计算那样插值。

随意舍入或转换整个表达式(例如cast(... as decimal(4,2)))以获得美观​​的报告,甚至将- 1.0替换为- 1e以强制浮点计算。

在这种情况下,

NTILE()并不是你真正想要的,因为它实际上将有序集的行号分成了组而不是值。如果这些实例恰好跨越交叉点,它将为相同值的两个实例分配不同的百分位数。然后,您必须按该值进行分组,并以与NTILE()相同的方式获取组的最大或最小百分位数以使用RANK()

答案 2 :(得分:1)

您的代码存在问题,因为NTILE分布不统一。如果您有213名学生,则最多的13个小组将有3名学生,后者87名将有2名学生。这不是您在百分比分布中理想的想法。

你可能想要使用RANK / ROWNUM然后除以得到%ile组。

答案 3 :(得分:0)

是否有拼写错误?

select NTILE(100) OVER (order by Score) PercentileRank 
from @temp

你的脚本看起来不错。如果你认为那里出了问题,你能澄清一下是什么吗?

答案 4 :(得分:0)

我知道这是一个老话题,但肯定会有很多关于这个话题的错误信息,这使得它在互联网上崭露头角。

NTILE并非设计用于计算百分等级(AKA百分比排名)

如果您使用NTILE计算百分比排名,那么您做错了。任何告诉你的人都会被误导和误解。如果您正在使用NTILE(100)并获得正确的答案,那纯属巧合。

蒂姆·莱纳完美地解释了这个问题。

  

"如果这些实例恰好跨越交叉点,它将为相同值的两个实例分配不同的百分位数。"

换句话说,使用NTILE计算学生根据他们的考试成绩排名的位置可以导致两名学生具有完全相同的考试成绩,获得不同的百分比等级值。相反,两名成绩不同的学生可以获得相同的百分比。

有关为什么NTILE是这项工作的错误工具的更详细解释,以及作为percent_rank的更好表现的替代方案,请参阅:令人讨厌的快速PERCENT_RANK。 http://www.sqlservercentral.com/articles/PERCENT_RANK/141532/