GoogleBigQuery SQL:使滚动平均子查询或联合对于大型数据集更加有效

问题描述 投票:0回答:2

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

  1. GBQ不允许“相关子查询”
  2. 由于我正在查询的数据量(+ 500m行),联接似乎要花费大量的时间(+3小时),并且我猜查询效率可能很低

基本上是针对每一行,我计算一些行的平均值,其中行应满足以下条件:(current_row_value-x <= other_row_value

使用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不接受相关的子查询。因此,这里是联接版本,其结果略有不同(省略了无法计算平均值的行),但仍然正确。我还添加了“ group by”中的所有列,因为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变得更有效。还尝试在500万行上运行查询的联接版本,这需要+1小时,因此我也期望失败。

sql google-bigquery correlated-subquery rolling-computation
2个回答
0
投票

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

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;

0
投票

您似乎想要一笔款项。并使用窗口功能:

select t.*,
       sum(quantity) over (order by orderid
                           range between 3 preceding and 1 preceding
                          ) as TheThingYouCallAnAverage
from t;
© www.soinside.com 2019 - 2024. All rights reserved.