在MS SQL中计算百分位排名
时间:2020-03-05 18:57:50 来源:igfitidea点击:
在MSSQL 2005中计算百分位排名(例如第90个百分位或者中位数)的最佳方法是什么?
我希望能够为单列分数选择第25,中位数和第75个百分位数(最好是在单个记录中,这样我就可以与平均值,最大值和最小值相结合)。因此,例如,结果的表输出可能是:
Group MinScore MaxScore AvgScore pct25 median pct75 ----- -------- -------- -------- ----- ------ ----- T1 52 96 74 68 76 84 T2 48 98 74 68 75 85
解决方案
回答
我可能会使用SQL Server 2005
row_number() over (order by score ) / (select count(*) from scores)
或者类似的规定。
回答
我会做类似的事情:
select @n = count(*) from tbl1 select @median = @n / 2 select @p75 = @n * 3 / 4 select @p90 = @n * 9 / 10 select top 1 score from (select top @median score from tbl1 order by score asc) order by score desc
这是正确的吗?
回答
我认为这将是最简单的解决方案:
SELECT TOP N PERCENT FROM TheTable ORDER BY TheScore DESC
其中N =(100个所需百分位数)。因此,如果我们希望所有行都位于第90个百分位,则可以选择前10%。
我不确定"最好在一条记录中"是什么意思。意思是计算单个记录的给定分数将落入哪个百分位吗?例如我们是否希望能够发表这样的陈述:"分数是83,这使我们处于第91个百分位"。 ?
编辑:好的,我想过更多关于问题,并提出了这种解释。我们是否在问如何计算特定百分位数的截止分数?例如这样的事情:要进入第90个百分点,得分必须大于78.
如果是这样,则此查询有效。不过,我不喜欢子查询,因此,根据子查询的目的,我可能会尝试找到一种更优雅的解决方案。但是,它确实返回具有单个分数的单个记录。
-- Find the minimum score for all scores in the 90th percentile SELECT Min(subq.TheScore) FROM (SELECT TOP 10 PERCENT TheScore FROM TheTable ORDER BY TheScore DESC) AS subq
回答
我已经在做更多的工作了,到目前为止,这是我要提出的:
CREATE PROCEDURE [dbo].[TestGetPercentile] @percentile as float, @resultval as float output AS BEGIN WITH scores(score, prev_rank, curr_rank, next_rank) AS ( SELECT dblScore, (ROW_NUMBER() OVER ( ORDER BY dblScore ) - 1.0) / ((SELECT COUNT(*) FROM TestScores) + 1) [prev_rank], (ROW_NUMBER() OVER ( ORDER BY dblScore ) + 0.0) / ((SELECT COUNT(*) FROM TestScores) + 1) [curr_rank], (ROW_NUMBER() OVER ( ORDER BY dblScore ) + 1.0) / ((SELECT COUNT(*) FROM TestScores) + 1) [next_rank] FROM TestScores ) SELECT @resultval = ( SELECT TOP 1 CASE WHEN t1.score = t2.score THEN t1.score ELSE t1.score + (t2.score - t1.score) * ((@percentile - t1.curr_rank) / (t2.curr_rank - t1.curr_rank)) END FROM scores t1, scores t2 WHERE (t1.curr_rank = @percentile OR (t1.curr_rank < @percentile AND t1.next_rank > @percentile)) AND (t2.curr_rank = @percentile OR (t2.curr_rank > @percentile AND t2.prev_rank < @percentile)) ) END
然后在另一个存储过程中,我这样做:
DECLARE @pct25 float; DECLARE @pct50 float; DECLARE @pct75 float; exec SurveyGetPercentile .25, @pct25 output exec SurveyGetPercentile .50, @pct50 output exec SurveyGetPercentile .75, @pct75 output Select min(dblScore) as minScore, max(dblScore) as maxScore, avg(dblScore) as avgScore, @pct25 as percentile25, @pct50 as percentile50, @pct75 as percentile75 From TestScores
它仍然不能完全满足我的要求。这将获得所有测试的统计信息;而我希望能够从其中具有多个不同测试的TestScores表中进行选择,并为每个不同的测试取回相同的统计信息(就像我在问题示例表中一样)。