it-swarm-es.tech

Cálculo de clasificaciones porcentuales en MS SQL

¿Cuál es la mejor manera de calcular las clasificaciones de percentiles (por ejemplo, el percentil 90 o la puntuación media) en MSSQL 2005?

Me gustaría poder seleccionar los percentiles 25, mediano y 75 para una sola columna de puntajes (preferiblemente en un solo registro para poder combinar con promedio, máximo y mínimo). Entonces, por ejemplo, la salida de la tabla de los resultados podría ser:

Group  MinScore  MaxScore  AvgScore  pct25  median  pct75
-----  --------  --------  --------  -----  ------  -----
T1     52        96        74        68     76      84
T2     48        98        74        68     75      85
26
Soldarnal

Creo que esta sería la solución más simple:

SELECT TOP N PERCENT FROM TheTable ORDER BY TheScore DESC

Donde N = (100 - percentil deseado). Entonces, si quisieras todas las filas en el percentil 90, seleccionarías el 10% superior.

No estoy seguro de lo que quieres decir con "preferiblemente en un solo registro". ¿Quiere decir calcular en qué percentil se ubicaría un puntaje dado para un solo registro? p.ej. ¿Desea poder hacer declaraciones como "su puntaje es 83, lo que lo coloca en el percentil 91". ?

EDITAR: OK, pensé un poco más sobre tu pregunta y se me ocurrió esta interpretación. ¿Estás preguntando cómo calcular la puntuación de corte para un percentil particular? p.ej. algo como esto: para estar en el percentil 90 debes tener un puntaje mayor a 78.

Si es así, esta consulta funciona. Sin embargo, no me gustan las subconsultas, así que dependiendo de para qué sirve, probablemente trataría de encontrar una solución más elegante. Sin embargo, devuelve un solo registro con una sola puntuación.

-- 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
15
Matt

Echa un vistazo al comando NTILE: ¡te dará percentiles con bastante facilidad!

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)
9
Elizabeth

Qué tal esto:

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
2
Paul

El percentil 50 es igual a la mediana. Al calcular otro percentil, digamos el 80, ordene los datos para el 80 por ciento de los datos en orden ascendente y el otro 20 por ciento en orden descendente, y tome el promedio de los dos valores medios.

NB: La consulta mediana ha existido durante mucho tiempo, pero no puedo recordar de dónde la obtuve exactamente, solo la modifiqué para calcular otros percentiles.

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
1
Kay Aliu

He estado trabajando en esto un poco más, y esto es lo que he encontrado hasta ahora:

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

Luego, en otro procedimiento almacenado hago esto:

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

Todavía no hace exactamente lo que estoy buscando. Esto obtendrá las estadísticas para todas las pruebas; mientras que me gustaría poder seleccionar de una tabla TestScores que tiene múltiples pruebas diferentes y recuperar las mismas estadísticas para cada prueba diferente (como lo he hecho en mi tabla de ejemplo en mi pregunta).

1
Soldarnal

El percentil se calcula por

(Rank -1) /(total_rows -1) cuando ordena los valores en orden ascendente.

La consulta a continuación le dará un valor de percentil entre 0 y 1. La persona con las calificaciones más bajas tendrá un percentil de 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
0
Debasmita

probablemente usaría un servidor SQL 2005

row_number () over (ordenar por puntuación)/(seleccionar recuento (*) de puntuaciones)

o algo por el estilo.

0
karl prosser

haría algo como:

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

¿es esto correcto?

0
syap