【发布时间】:2017-10-17 21:18:58
【问题描述】:
分析波动性太大的数据系列中的趋势很困难。在许多情况下,使用平滑技术(如移动平均线或移动总和)很有用。有很多工具可以执行这种类型的操作,但是当我们谈论数百万行时,直接在 Google Big Query 等云环境中执行此操作很有用。
我的问题是:如何在 Google Big Query 上计算移动总和/平均值?
【问题讨论】:
标签: google-bigquery
分析波动性太大的数据系列中的趋势很困难。在许多情况下,使用平滑技术(如移动平均线或移动总和)很有用。有很多工具可以执行这种类型的操作,但是当我们谈论数百万行时,直接在 Google Big Query 等云环境中执行此操作很有用。
我的问题是:如何在 Google Big Query 上计算移动总和/平均值?
【问题讨论】:
标签: google-bigquery
以下是 BigQuery 标准 SQL
#standardSQL
SELECT
pickup_date,
number_of_trip,
AVG(number_of_trip) OVER (ORDER BY day RANGE BETWEEN 6 PRECEDING AND CURRENT ROW) AS mov_avg_7d,
AVG(number_of_trip) OVER (ORDER BY day RANGE BETWEEN 27 PRECEDING AND CURRENT ROW) AS mov_avg_28d
FROM (
SELECT
DATE(pickup_datetime) AS pickup_date,
UNIX_DATE(DATE(pickup_datetime)) AS day,
COUNT(*) AS number_of_trip
FROM `nyc-tlc.yellow.trips`
GROUP BY 1, 2
)
WHERE pickup_date>'2013-01-01'
乍一看 - 这个答案看起来与 OP 的答案非常相似,所以只有少数几个人知道这个答案有什么不同:
首先(也是最不重要的) - BigQuery 团队强烈推荐使用 BigQuery 标准 SQL - 除非有非常好的理由使用旧版 SQL - 例如因为范围快照或旧版 sql 非常特定的东西
其次,也是最重要的 - 在这种情况下使用 OVER 和 ROWS 并不是最佳选择,因为它计算的是行数而不是天数,所以如果 - 偶然 - 错过了任何一天 - 计算将使用过去 8 天和 29 天分别(而不是 7 和 28)
在这种情况下,应该使用 OVER 和 RANGE
【讨论】:
我花了很多时间研究这个答案但没有成功,所以我认为与更多人分享它是值得的。
解决方案:为了得到答案,我使用了 Big Query 的分析函数 OVER 和 ROWS (https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#analytic-function-syntax)。下面是一个使用 BigQuery 中提供的公共数据的出租车行程 7 天移动平均值和 28 天移动平均值示例:
SELECT
pickup_date,
number_of_trip,
avg(number_of_trip) OVER (ORDER BY pickup_date ROWS BETWEEN 6 PRECEDING and CURRENT ROW) AS mov_avg_7d,
avg(number_of_trip) OVER (ORDER BY pickup_date ROWS BETWEEN 27 PRECEDING and CURRENT ROW) AS mov_avg_28d
FROM
(SELECT
date(pickup_datetime) as pickup_date,
count(*) as number_of_trip,
FROM [nyc-tlc:yellow.trips]
group each by 1
order by 1)
where pickup_date>'2013-01-01'
小心反模式!网上有很多帖子建议使用JOIN 甚至CROSS JOIN 来实现相同结果的解决方案。但是,根据 Big Query 文档 (https://cloud.google.com/bigquery/docs/best-practices-performance-patterns),这些方法是反模式。这意味着,如果您使用蛮力解决问题,那么对于大量数据而言,性能将是一个问题。
【讨论】: