Google bigquery BigQuery递归计算列
我需要使用表中的数据创建一个计算列。此计算列x_平均值基于计算平均值公式的应用,其中x_平均值的下一个值需要相同计算列的上一个值。我最后称之为递归计算,因为下一个值需要上一个值。该公式与以下公式有些类似:Google bigquery BigQuery递归计算列,google-bigquery,Google Bigquery,我需要使用表中的数据创建一个计算列。此计算列x_平均值基于计算平均值公式的应用,其中x_平均值的下一个值需要相同计算列的上一个值。我最后称之为递归计算,因为下一个值需要上一个值。该公式与以下公式有些类似: x_average = (days + (x_average * stock)) ----------------------------- (input + stock) 该表类似于以下示例: +----------------
x_average = (days + (x_average * stock))
-----------------------------
(input + stock)
该表类似于以下示例:
+-----------------------------------+
+ date | days | input | stock +
+-----------------------------------+
+ 2020-01-03 | 11 | 5 | 5 +
+ 2020-01-05 | 3 | 1 | 2 +
+ 2020-01-15 | 21 | 7 | 1 +
+ 2020-01-16 | 17 | 12 | 4 +
+ 2020-01-22 | 15 | 4 | 3 +
+ (more...)
+-----------------------------------+
如何创建可以选择表和计算列x_average的查询
预期结果类似于:
+-----------------------------------------------+
+ date | days | input | stock | x_average +
+-----------------------------------------------+
+ 2020-01-03 | 11 | 5 | 5 | 1.1 +
+ 2020-01-05 | 3 | 1 | 2 | 1.733 +
+ 2020-01-15 | 21 | 7 | 1 | 2.841 +
+ 2020-01-16 | 17 | 12 | 4 | 1.772 +
+ 2020-01-22 | 15 | 4 | 3 | 2.902 +
+ (more...)
+-----------------------------------------------+
该表可以在1到365行之间。下面是用于BigQuery标准SQL的,并使用BQ的脚本功能
#standardSQL
declare a, b, c array<float64>;
declare i, len int64;
/*
create temp table input_table as
select '2020-01-03' date, 11 days, 5 input , 5 stock union all
select '2020-01-05', 3, 1, 2 union all
select '2020-01-15', 21, 7, 1 union all
select '2020-01-16', 17, 12, 4 union all
select '2020-01-22', 15, 4, 3;
*/
set (i, len, c, a, b) = (
select as struct 1, count(1), [1.0],
array_agg(days / (input + stock) order by date),
array_agg(stock / (input + stock) order by date)
from input_table
);
while i <= len do
if i = 1 then set c = [round(a[ordinal(i)], 3)];
else set c = c || [a[ordinal(i)] + c[ordinal(i - 1)] * b[ordinal(i)]];
end if;
set i = i + 1;
end while;
create temp table output as
select * except(i), round(c[ordinal(i)], 3) as x_average
from (
select *, row_number() over(order by date) i
from input_table
);
select * from output order by date;
当您在表input_table上运行它时,或者您可以取消注释temp table部分以使用问题中的虚拟数据进行测试,您会得到如下结果
单击最后一行上的“查看结果”以查看结果表-输出
注意:正如我在评论中提到的,有很多方法可以实现您的逻辑,但我选择了一种使用脚本的方法。例如,你可以用JS UDF进行实验——基于上面脚本中的代码,这应该是一个简单的练习在我看来,你忽略了什么是常见的行为,所以——投票选出有用的答案,并接受其中最好的一个!这是SO文化的重要组成部分:O请检查你以前的文章并考虑上面的问题,这将激励我们回答你的新问题。投票结束,谢谢你的几个问题:1。就行数2而言,表有多大。应该是一些额外的字段,用于定义处理行的顺序-您的表中是否有可用于此操作的行?如果不是,你必须添加它!!!1.从1到365行2。日期确定了。添加日期是有意义的,但要求它们是不同的,这样就不会有日期相同的行!也只有300行左右,这使得它有很多简单的方法。如果时间允许的话,我会看一看的,除非其他人会跳得更快:首先谢谢你的回复。我在一个脚本中通过数组和循环使用类似的方法解决了这个问题。但我想知道的是,是否有可能只使用选择来解决这个问题,而不使用WHILEs、LOOPs、array等循环。一个解决方案,其中一个或多个选择使用或不使用窗口函数,可以解决递归计算。因此,我已经提出了另一个解决方案,其中循环部分是在JS UDF中完成的,但是如果不使用脚本和JS,我如何解决它呢?可能吗?其他数据库允许“递归CTE”,这将是一个很好的解决方案,作为一个不需要脚本的独立查询,我想这是您想要的。然而,BQ并不支持这一点。@ CaytBoeNeli——如果有帮助和接受,请考虑投票。同时,为了满足您不使用脚本并使用纯基于集合的方法实现它的愿望—我认为在这种特殊情况下是可能的—但实际上,如果有相对简单的方法使用脚本或js udf,那么花时间想出棘手的解决方案的原因是什么?但是,再一次——我认为这是可行的!我的目标是看看这是否可能,解决方案是否非常复杂,这也将是一个学习SQL新技巧的机会,可以解决这个特定问题。