在同一查询中返回分组值的平均值以及该值的前 n% 的平均值?

Posted

技术标签:

【中文标题】在同一查询中返回分组值的平均值以及该值的前 n% 的平均值?【英文标题】:Return the mean of a grouped value along with the mean of the top n% of that value in the same query? 【发布时间】:2021-01-04 19:16:19 【问题描述】:

我需要编写一个查询来返回组中字段的平均值以及组中这些字段的前 33% 值的平均值。

UserId | Sequence | Value | Value2
-------|----------|-------|-------
1      | 1        | 5     | 0
1      | 2        | 10    | 15
1      | 3        | 15    | 20
1      | 4        | NULL  | 25
1      | 5        | NULL  | 30
1      | 6        | NULL  | 60

返回还需要包含用于计算均值的分母,我想按用户分组并返回如下内容:

UserId | ValueMean | ValueDenom | ValueTopNMean | ValueTopNDenom | Value2Mean | Value2Denom | Value2TopNMean | Value2TopNDenom
-------|-----------|------------|---------------|----------------|------------|-------------|----------------|----------------
1      | 10        | 3          | 15            | 1              | 25         | 6           | 45             | 2

我尝试了各种窗口函数(NTILE、PERCENT_RANK 等),但棘手的是我有多个值字段需要进行相同的操作,并且每个值字段的分母会有所不同(n但是,% 将保持不变)。如果我不清楚或者您需要更多信息,请告诉我。

【问题讨论】:

向我们展示您的尝试。 【参考方案1】:

可以使用聚合函数轻松计算总体平均值和最高值,以及非null 值的计数。

至于前 N 个值的平均值和计数:您可以在子查询中使用 ntile() 来首先识别相关行,然后在外部查询的聚合函数内的条件表达式中使用该信息。

select
    userid,
    avg(value)   avg_value,
    count(value) cnt_value,
    max(value)   top_value,
    avg(case when ntile_value = 1 then value end)    avg_topn_value,
    sum(case when ntile_value = 1 then 1 else 0 end) cnt_topn_value
from (select t.*, ntile(3) over(order by value) ntile_value from mytable t) t
group by userid

【讨论】:

以上是关于在同一查询中返回分组值的平均值以及该值的前 n% 的平均值?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 聚合函数 和 分组查询(初级)

MySQL 聚合函数 和 分组查询(初级)

mysql之聚合函数

聚合函数和分组查询(快掏出小本本记下来这些锦囊妙计)

聚合函数和分组查询(快掏出小本本记下来这些锦囊妙计)

如何仅按某个列值的前几个字母对 SQL 查询进行分组?