Google BigQuery SQL:使滚动平均子查询或加入对大型数据集更有效

Posted

技术标签:

【中文标题】Google BigQuery SQL:使滚动平均子查询或加入对大型数据集更有效【英文标题】:GoogleBigQuery SQL: Make Rolling Avg Subquery or Join More Efficient For Large Dataset 【发布时间】:2019-11-19 22:53:12 【问题描述】:

首先,我已经弄清楚了如何使用子查询或联接来获得我需要的东西。由于缺乏GBQ经验,我一直面临的问题:

    GBQ 不允许“相关子查询” 因为我要查询的数据量(+500m 行),连接似乎需要大量时间(+3 小时),我猜查询可能效率低下

基本上对于每一行,我正在寻找计算一些行的平均值,其中行应该满足条件 where (current_row_value-x

使用https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_join 作为数据,并进行以下查询:

SELECT *, (select avg(Quantity) from OrderDetails as table_2 where table_2.OrderId between table_1.OrderId-3 and table_1.OrderId-1) as avg_quant_3 FROM OrderDetails as table_1 order by OrderId asc

它输出我需要的结果:

Number of Records: 518
OrderDetailID   OrderID ProductID   Quantity    avg_quant_3
1   10248   11  12  null
2   10248   42  10  null
3   10248   72  5   null
4   10249   14  9   27
5   10249   51  40  27
6   10250   41  10  76
7   10250   51  35  76
8   10250   65  15  76
9   10251   22  6   136
10  10251   57  15  136
11  10251   65  20  136
12  10252   20  40  150

我不能使用上述格式的查询,因为 GBQ 不接受相关子查询。所以这里是连接版本,结果有点不同(省略了无法计算平均值的行),但仍然正确。我还在“分组依据”中添加了所有列,因为 GBQ 不会接受使用聚合函数而不分组或聚合所有选择的列的查询:

SELECT table_1.OrderDetailID, table_1.OrderID,table_1.ProductID, table_1.Quantity, sum(table_2.quantity) FROM OrderDetails as table_1
join OrderDetails as table_2 on table_2.OrderId between table_1.OrderId-3 and table_1.OrderId-1  
group by table_1.OrderDetailID, table_1.OrderID,table_1.ProductID, table_1.Quantity
Number of Records: 515
OrderDetailID   OrderID ProductID   Quantity    sum(table_2.quantity)
4   10249   14  9   27
5   10249   51  40  27
6   10250   41  10  76
7   10250   51  35  76
8   10250   65  15  76
9   10251   22  6   136
10  10251   57  15  136
11  10251   65  20  136
12  10252   20  40  150

这里的问题是加入需要 +3 小时,实际上由于耗时太长而失败。从我目前使用 GBQ 的经验来看,连接似乎需要很长时间,但我又一次查询了一个大型数据集。我想知道是否有任何其他方法可以通过更有效的查询来获取此信息,并且我希望将来可以学到一些东西以提高 GBQ 的效率。还尝试在 5m 行上运行查询的联接版本,它需要 +1 小时,所以我也预计会失败。

【问题讨论】:

我只是不明白AVG() 将如何产生比列中任何内容都大的数字。 【参考方案1】:

您能否显示您在尝试运行“相关子查询”时遇到的错误?下面的查询对我有用:

create temp table table1
as select 1 as x, 2 as y
 union all select 3, 4;

create temp table table2
as select 3 x;

select *, (select avg(y) from table1 where table1.x = table2.x)
from table2
order by x;

【讨论】:

【参考方案2】:

你似乎想要一笔钱。并使用窗口函数:

select t.*,
       sum(quantity) over (order by orderid
                           range between 3 preceding and 1 preceding
                          ) as TheThingYouCallAnAverage
from t;

【讨论】:

以上是关于Google BigQuery SQL:使滚动平均子查询或加入对大型数据集更有效的主要内容,如果未能解决你的问题,请参考以下文章

Google BigQuery 的限制?

BigQuery SQL:平均值、几何平均值、去除异常值、中值

BigQuery 中的多个左连接

Google 标准 SQL UDF - 写入 BigQuery

Google BigQuery:性能(详细)

sql 已完成购买 - Google BigQuery