在 bigquery 中计算 7、14 和 30 天移动平均线

Posted

技术标签:

【中文标题】在 bigquery 中计算 7、14 和 30 天移动平均线【英文标题】:Calculate 7, 14 and 30 day moving average in bigquery 【发布时间】:2019-02-28 08:04:25 【问题描述】:

我正在玩 bigquery。我有 IoT 正常运行时间记录作为输入:

+---------------+-------------+----------+------------+
|   device_id   |  reference  |  uptime  | timestamp  |
+---------------+-------------+----------+------------+
| 1             | 1000-5      |  0.7     | 2019-02-12 |
| 2             | 1000-6      |  0.9     | 2019-02-12 |
| 1             | 1000-5      |  0.8     | 2019-02-11 |
| 2             | 1000-6      |  0.95    | 2019-02-11 |
+---------------+-------------+----------+------------+

我想计算按设备分组的正常运行时间的 7、14 和 30 天移动平均值。输出应如下所示:

+---------------+-------------+---------+--------+--------+
|   device_id   |  reference  |  avg_7  | avg_14 | avg_30 |
+---------------+-------------+---------+--------+--------+
| 1             | 1000-5      |  0.7    | ..     | ..     |
| 2             | 1000-6      |  0.9    | ..     | ..     |
+---------------+-------------+---------+--------+--------+

我尝试过的:

SELECT
    device_id,
    AVG(uptime) OVER (ORDER BY day RANGE BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7d
FROM (
  SELECT device_id, uptime, UNIX_DATE(DATE(timestamp)) as day FROM `uptime_recordings`
)
GROUP BY device_id, uptime, day

我有 1000 个不同设备和 200k 个读数的记录。分组不起作用,查询返回 20 万条记录而不是 1000 条。有什么想法有什么问题吗?

【问题讨论】:

【参考方案1】:

我有 1000 个不同设备和 200k 个读数的记录。分组不起作用,查询返回 20 万条记录而不是 1000 条。有什么想法有什么问题吗?

GROUP BY device_id, day代替GROUP BY device_id, uptime, day

一个完整的工作查询:

WITH data 
AS (
  SELECT title device_id, views uptime, datehour timestamp
  FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
  WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-09'
  AND wiki='br'
  AND title='Chile'
)

SELECT device_id, day
  , AVG(uptime) OVER (PARTITION BY device_id ORDER BY UNIX_DATE(day) RANGE BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7d
FROM (
  SELECT device_id, AVG(uptime) uptime, (DATE(timestamp)) as day
  FROM `data`
  GROUP BY device_id, day
)

编辑:根据 cmets 的要求,不确定总结所有 7d 平均值的目标是什么:

WITH data 
AS (
  SELECT title device_id, views uptime, datehour timestamp
  FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
  WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-09'
  AND wiki='br'
  AND title IN ('Chile', 'Saozneg')
)

SELECT device_id, AVG(avg_7d) avg_avg_7d
FROM (
  SELECT device_id, day
    , AVG(uptime) OVER (PARTITION BY device_id ORDER BY UNIX_DATE(day) RANGE BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7d
  FROM (
    SELECT device_id, AVG(uptime) uptime, (DATE(timestamp)) as day
    FROM `data`
    GROUP BY device_id, day
  )
)
GROUP BY device_id 

【讨论】:

谢谢 Felipe :-) 我怎样才能按 device_id 分组而不按天分组?我还能获得 7 天平均值吗? 就像我粘贴的查询一样? 我无法删除按时间戳分组,因为“SELECT 列表表达式引用了既不分组也不聚合的列时间戳”。我希望 avg_7d 不是每天和每个 device_id,而是每个 device_id。 不确定总结所有 7d 平均值的目的是什么,但请检查我添加的查询

以上是关于在 bigquery 中计算 7、14 和 30 天移动平均线的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 计算两个日期范围重叠

通过命令行在 BigQuery 中加载数据时出错:已更新

在 BigQuery 中计算不同的 concat

BigQuery 中消耗的时隙时间

使用 BigQuery 计算当前 7 天的活跃用户?

在 Bigquery 中按用户计算登录之间的时间