我有一列数据,其中一些是 NULL 值,我希望从中提取单个 90% 的值:
ColA
-----
NULL
100
200
300
NULL
400
500
600
700
800
900
1000
对于上述内容,我正在寻找一种技术,它在搜索第 90 个百分位时返回值 900,在第 80 个百分位处返回 800,等等。类似的函数是 AVG(ColA),它为上述数据返回 550,或 MIN( ColA) 返回 100 等。
有什么建议么?
如果您想准确获得第 90 个百分位值,不包括 NULL,我建议直接进行计算。以下版本计算行数和行数,并选择合适的值:
select max(case when rownum*1.0/numrows <= 0.9 then colA end) as percentile_90th
from (select colA,
row_number() over (order by colA) as rownum,
count(*) over (partition by NULL) as numrows
from t
where colA is not null
) t
我将条件放在 SELECT 子句而不是 WHERE 子句中,因此您可以轻松获得第 50 个百分位、第 17 个或任何您想要的值。
WITH
percentiles AS
(
SELECT
NTILE(100) OVER (ORDER BY ColA) AS percentile,
*
FROM
data
)
SELECT
*
FROM
percentiles
WHERE
percentile = 90
注意:如果数据的观测值少于 100 个,则并非所有百分位数都有值。同样,如果您有超过 100 个观察值,则某些百分位数将包含更多值。
从 SQL Server 2012 开始,有现在PERCENTILE_DISC
和PERCENTILE_CONT
逆分布函数。这些(到目前为止)仅可用作窗口函数,而不是聚合函数,因此由于缺少分组,您必须删除冗余结果,例如使用DISTINCT
or TOP 1
:
WITH t AS (
SELECT *
FROM (
VALUES(NULL),(100),(200),(300),
(NULL),(400),(500),(600),(700),
(800),(900),(1000)
) t(ColA)
)
SELECT DISTINCT percentile_disc(0.9) WITHIN GROUP (ORDER BY ColA) OVER()
FROM t
;