如何一次性计算表中所有分组下99百分位以下的时长统计指标
如何一次性计算表中所有分组下99百分位以下的时长统计指标
嗨,我来帮你搞定这个批量统计的问题!你原来的查询只针对单个name值,要扩展到所有name其实很简单,核心就是给窗口函数加上分组分区的逻辑,让每个name单独计算百分位,再按name聚合统计指标就行。
方法一:基于你原有的NTILE逻辑修改
你原来用NTILE(100)划分百分位,只要在窗口函数的OVER子句里加上PARTITION BY name,就能让每个name的duration单独排序分桶。之后外层按name分组计算统计量即可:
SELECT name, MIN(duration) AS min_duration, MAX(duration) AS max_duration, STDDEV(duration) AS stddev_duration, AVG(duration) AS avg_duration FROM (SELECT name, duration, NTILE(100) OVER (PARTITION BY name ORDER BY duration) AS percentile FROM tasks) t WHERE percentile < 99 GROUP BY name;
小说明:
PARTITION BY name会把数据按name拆分成独立的组,每个组内部单独计算百分位,不会和其他name的数据混在一起。- 外层的
GROUP BY name会把每个name对应的前98个桶(也就是99百分位以下)的数据聚合起来,算出你需要的四个指标。
方法二:更精准的百分位筛选(推荐)
NTILE(100)的小问题在于,如果某个name的记录数不是100的整数倍,分桶大小会不均匀,可能导致百分位划分不够精准。如果想要更准确的99百分位筛选,可以用PERCENTILE_DISC或PERCENTILE_CONT先算出每个name的99百分位数值,再筛选出小于该值的记录统计:
WITH name_99th_percentile AS ( SELECT name, -- PERCENTILE_DISC返回分组中实际存在的、最接近99%的数值 PERCENTILE_DISC(0.99) WITHIN GROUP (ORDER BY duration) AS p99_duration FROM tasks GROUP BY name ) SELECT t.name, MIN(t.duration) AS min_duration, MAX(t.duration) AS max_duration, STDDEV(t.duration) AS stddev_duration, AVG(t.duration) AS avg_duration FROM tasks t JOIN name_99th_percentile n ON t.name = n.name WHERE t.duration < n.p99_duration GROUP BY t.name;
两种百分位函数的区别:
PERCENTILE_DISC:返回分组中实际存在的、最接近指定百分位的数值(离散型)。PERCENTILE_CONT:返回基于线性插值计算的百分位数值(连续型,可能是数据中不存在的数值)。
你可以根据业务需求选择合适的函数。
备注:内容来源于stack exchange,提问作者Mike S
相关产品推荐
相关产品推荐

