在 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 天移动平均线的主要内容,如果未能解决你的问题,请参考以下文章