it-swarm-id.com

Menghitung peringkat persentil dalam MS SQL

Apa cara terbaik untuk menghitung peringkat persentil (mis. Persentil ke-90 atau skor median) di MSSQL 2005?

Saya ingin dapat memilih persentil ke-25, median, dan ke-75 untuk satu kolom skor (sebaiknya dalam satu catatan sehingga saya dapat menggabungkan dengan rata-rata, maks, dan minimum). Jadi misalnya, output tabel dari hasil mungkin:

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

Saya akan berpikir bahwa ini akan menjadi solusi paling sederhana:

SELECT TOP N PERCENT FROM TheTable ORDER BY TheScore DESC

Di mana N = (100 - persentil yang diinginkan). Jadi jika Anda ingin semua baris dalam persentil ke-90, Anda akan memilih 10% teratas.

Saya tidak yakin apa yang Anda maksud dengan "sebaiknya dalam satu rekaman". Apakah maksud Anda menghitung persentil mana skor yang diberikan untuk satu catatan akan jatuh ke dalam? misalnya apakah Anda ingin dapat membuat pernyataan seperti "skor Anda adalah 83, yang menempatkan Anda dalam persentil ke-91." ?

EDIT: OK, saya memikirkan lebih lanjut tentang pertanyaan Anda dan muncul dengan interpretasi ini. Apakah Anda bertanya bagaimana cara menghitung skor cutoff untuk persentil tertentu? misalnya sesuatu seperti ini: untuk berada di persentil ke-90 Anda harus memiliki skor lebih dari 78.

Jika demikian, kueri ini berfungsi. Saya tidak suka sub-kueri, jadi tergantung pada apa tujuannya, saya mungkin akan mencoba menemukan solusi yang lebih elegan. Namun, itu mengembalikan rekor tunggal dengan skor tunggal.

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

Lihatlah perintah NTILE - ini akan memberi Anda persentil dengan mudah!

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

Bagaimana dengan ini:

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

Persentil ke-50 sama dengan median. Saat menghitung persentil lain, katakanlah yang ke-80, urutkan data untuk 80 persen data dalam urutan menaik dan 20 persen lainnya dalam urutan menurun, dan ambil rata-rata dari dua nilai tengah.

NB: Permintaan median telah ada sejak lama, tetapi tidak dapat mengingat dari mana tepatnya saya mendapatkannya, saya hanya mengubahnya untuk menghitung persentil lainnya.

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

Saya telah mengerjakan ini sedikit lagi, dan inilah yang saya buat sejauh ini:

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

Kemudian dalam prosedur tersimpan lainnya saya melakukan ini:

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

Masih tidak melakukan apa yang saya cari. Ini akan mendapatkan statistik untuk semua tes; sedangkan saya ingin dapat memilih dari tabel TestScores yang memiliki beberapa tes berbeda di dalamnya dan mendapatkan kembali statistik yang sama untuk setiap tes yang berbeda (seperti yang saya miliki di tabel contoh saya dalam pertanyaan saya).

1
Soldarnal

saya mungkin akan menggunakan server sql 2005 

row_number () over (diurutkan berdasarkan skor)/(pilih hitungan (*) dari skor)

atau sesuatu di sepanjang garis itu. 

0
karl prosser

saya akan melakukan sesuatu seperti:

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

apakah ini benar?

0
syap