在MS SQL中计算百分位排名

在MS SQL中计算百分位排名,sql,sql-server,math,Sql,Sql Server,Math,计算百分位排名的最佳方法是什么,例如MSSQL 2005中的第90百分位或中位数 我希望能够为一列分数选择第25、中位数和第75个百分位数,最好是在一个记录中,这样我就可以结合平均值、最大值和最小值。例如,结果的表格输出可能是: Group MinScore MaxScore AvgScore pct25 median pct75 ----- -------- -------- -------- ----- ------ ----- T1 52 96

计算百分位排名的最佳方法是什么,例如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

我可能会在SQLServer2005中使用

按分数排序的行数/从分数中选择计数*

或者类似的东西

我会这样做:

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%

我不知道你说的最好在一张唱片里是什么意思。你的意思是计算一个记录的某个给定分数将属于哪个百分位数?e、 g.你是否希望自己的分数达到83分,这将你排在第91个百分点

编辑:好的,我对你的问题进行了更多的思考,并提出了这个解释。你是在问如何计算特定百分位数的截止分数吗?e、 类似这样的情况:要进入第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

它仍然不完全符合我的要求。这将获得所有测试的统计信息;然而,我希望能够从一个包含多个不同测试的TestScores表中进行选择,并获得每个不同测试的相同统计数据,就像我在问题示例表中所做的一样。

第50个百分位数与中位数相同。当计算其他百分位时,比如第80个百分位,将80%的数据按升序排序,另20%按降序排序,并取两个中间值的平均值

注:中位数查询已经存在很长时间了,但我记不起它的确切来源,我只是修改它来计算其他百分位数

DECLARE @Temp TABLE(Id INT IDENTITY(1,1), DATA DECIMAL(10,5))

INSERT INTO @Temp VALUES(0)
INSERT INTO @Temp VALUES(2)
INSERT INTO @Temp VALUES(8)
INSERT INTO @Temp VALUES(4)
INSERT INTO @Temp VALUES(3)
INSERT INTO @Temp VALUES(6)
INSERT INTO @Temp VALUES(6)
INSERT INTO @Temp VALUES(6) 
INSERT INTO @Temp VALUES(7)
INSERT INTO @Temp VALUES(0)
INSERT INTO @Temp VALUES(1)
INSERT INTO @Temp VALUES(NULL)


--50th percentile or median
SELECT ((
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 50 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA
                ) AS A
        ORDER BY DATA DESC) + 
        (
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 50 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA DESC
                ) AS A
        ORDER BY DATA ASC)) / 2.0


--90th percentile 
SELECT ((
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 90 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA
                ) AS A
        ORDER BY DATA DESC) + 
        (
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 10 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA DESC
                ) AS A
        ORDER BY DATA ASC)) / 2.0


--75th percentile
SELECT ((
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 75 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA
                ) AS A
        ORDER BY DATA DESC) + 
        (
        SELECT TOP 1 DATA
        FROM   (
                SELECT  TOP 25 PERCENT DATA
                FROM    @Temp
                WHERE   DATA IS NOT NULL
                ORDER BY DATA DESC
                ) AS A
        ORDER BY DATA ASC)) / 2.0

查看NTILE命令-它将非常容易地为您提供百分位数

SELECT  SalesOrderID, 
    OrderQty,
    RowNum = Row_Number() OVER(Order By OrderQty),
    Rnk = RANK() OVER(ORDER BY OrderQty),
    DenseRnk = DENSE_RANK() OVER(ORDER BY OrderQty),
    NTile4  = NTILE(4) OVER(ORDER BY OrderQty)
FROM Sales.SalesOrderDetail 
WHERE SalesOrderID IN (43689, 63181)
这个怎么样:

SELECT
  Group,
  75_percentile =  MAX(case when NTILE(4) OVER(ORDER BY score ASC) = 3 then score  else 0 end),
  90_percentile =  MAX(case when NTILE(10) OVER(ORDER BY score  ASC) = 9 then score  else 0 end)     
FROM TheScore
GROUP BY Group

百分位数由以下公式计算:

按升序对值排序时,秩-1/行总数-1

下面的查询将为您提供介于0和1之间的百分位值。得分最低的人将有0个百分点

SELECT Name, marks, (rank_1-1)/((select count(*) as total_1 from table)-1)as percentile_rank
from
(
SELECT Name,
       Marks,
       RANK() OVER (ORDER BY Marks) AS rank_1
       from table
) as A
SELECT Name, marks, (rank_1-1)/((select count(*) as total_1 from table)-1)as percentile_rank
from
(
SELECT Name,
       Marks,
       RANK() OVER (ORDER BY Marks) AS rank_1
       from table
) as A