如何在 Big Query 的移动窗口中找到特定组中三个最大值的平均值?

Posted

技术标签:

【中文标题】如何在 Big Query 的移动窗口中找到特定组中三个最大值的平均值?【英文标题】:How to find the average of the three maximum values in a specific group in a moving window in Big Query? 【发布时间】:2021-12-02 21:38:48 【问题描述】:

我有一个数据集,如下表所示。我想在按 id 分组的滚动 12 个月窗口中找到最大三个值的平均值。

id     date         value
id1    2020/01/01   500 
id1    2021/02/01   300  
id1    2021/03/01   150
id1    2021/08/01   100
id1    2021/12/01   400
id2    2020/01/01   50
id2    2020/02/01   900
id2    2021/12/01   100

所以我的预期输出是:

id     date         value
id1    2020/01/01   500 
id1    2021/02/01   300  
id1    2021/03/01   225
id1    2021/08/01   183.33
id1    2021/12/01   283.33
id2    2020/01/01   50
id2    2020/02/01   500
id2    2021/12/01   100

即对于id12021/12/01:(400+300+150)/3 = 283.33,这是组 ID1 滚动 12 个月窗口中三个最大值的平均值。

我设法做到了这一点:

CREATE TEMP FUNCTION avg_array(arr ANY TYPE) AS ((
SELECT AVG(val) FROM(
SELECT val FROM UNNEST(arr) val ORDER BY val DESC LIMIT 3)
)
);

SELECT id, date, avg_array(val_arr)
FROM (
SELECT
id, date, ARRAY_AGG(value) OVER (
PARTITION BY id
ORDER BY id, date DESC ROWS BETWEEN CURRENT ROW AND 11 FOLLOWING
) as val_arr
FROM  `table` )

这可行,但我觉得必须有更好的方法来做到这一点。具体来说,我不知道如何从 OVER 中获取最大三个的平均值,而不是创建一个单独的函数。

(如果无法将日期窗口与查找最大值相结合,那么知道如何在不创建单独函数的情况下找到任何group by 组中最大值三个的平均值也很有用)

`

【问题讨论】:

【参考方案1】:

在您的代码中,缺少“PARTITION BY id,EXTRACT(YEAR FROM date)”语句中的日期年份。

CREATE TEMP FUNCTION avg_array(arr ANY TYPE) AS ((
SELECT AVG(val) FROM(
SELECT val FROM UNNEST(arr) val ORDER BY val DESC LIMIT 3))
);
 
SELECT id, date, avg_array(val_arr)
FROM (
SELECT
id, date, ARRAY_AGG(value) OVER (
PARTITION BY id,EXTRACT(YEAR FROM date)
ORDER BY id, date DESC ROWS BETWEEN CURRENT ROW AND 11 FOLLOWING
) as val_arr
FROM  `table` )
order by id,date asc

在这里,你可以看到一个示例代码来获取一个组的最多 3 个数字:

select id,AVG(value) as vg from (
select id,date,value from (
select id, date, value  from `table`
order by value desc) a limit 3
) b group by id

你可以在this link看到更多关于over function的信息。

【讨论】:

【参考方案2】:

考虑以下方法

select id, date, 
  (select round(avg(value), 2) from (
     select value from t.arr value
     order by value desc 
     limit 3
  )) value
from (
  select *, array_agg(value) over last_12_month arr from table
  window last_12_month as (partition by id 
    order by 12 * (extract(year from date)) + extract(month from date)
     range between 11 preceding and current row
  )
) t             

如果应用于您问题中的样本数据 - 输出是

【讨论】:

你试过了吗?

以上是关于如何在 Big Query 的移动窗口中找到特定组中三个最大值的平均值?的主要内容,如果未能解决你的问题,请参考以下文章

BIG QUERY SQL:使用移动参考标记滑动时间窗口上的日期

如何将 .gz 文件上传到 Google Big Query?

如何在 Big Query 的标准 SQL 中使用通配符为特定分区查询多个表

在 Big Query 的表中查找特定条件的属性计数

如何在 BIG QUERY 中仅选择增量记录

如何在 Google Big Query 中正确使用 GROUP BY 命令?