Google bigquery 自定义滚动计算

Google bigquery 自定义滚动计算,google-bigquery,Google Bigquery,假设我有一个模型,其中At和Bt由以下等式控制: A(t) = { WHEN B(t-1) < 10 : B(t-1) WHEN B(t-1) >=10 : B(t-1) / 6 } B(t) = A(t) * 2 也就是说,我们知道At=0和Bt=0的值 对于每一行,我们希望使用上述方程式计算A和B的值 最终表格应为: | t | A | B | |---|---|----| | 0 | 0 | 9 | | 1 | 9 | 18 | | 2 | 3 | 6 | |

假设我有一个模型,其中At和Bt由以下等式控制:

A(t) = {
  WHEN B(t-1) < 10 : B(t-1)
  WHEN B(t-1) >=10 : B(t-1) / 6
}

B(t) = A(t) * 2
也就是说,我们知道At=0和Bt=0的值

对于每一行,我们希望使用上述方程式计算A和B的值

最终表格应为:

| t | A | B  |
|---|---|----|
| 0 | 0 | 9  |
| 1 | 9 | 18 |
| 2 | 3 | 6  |
| 3 | 6 | 12 |
| 4 | 2 | 4  |
我们尝试使用滞后,但由于模型的递归性质,我们最终只得到t=1时的A&B

创建临时函数A_fnb_prev FLOAT64作为 案例 当b_prev<10时,则b_prev ELSE b_prev/6.0 终止 ; 选择 T 当t=0时,则A ELSE A_fnLAGB超过订单,t结束为A, 当t=0时,则B的其他A_fnLAGB超过订单t*2,结束为B 从模型 按t排序; 产生:

| t | A    | B    |
|---|------|------|
| 0 | 0    | 9    |
| 1 | 9    | 18   |
| 2 | null | null |
| 3 | null | null |
| 4 | null | null |
每一行都依赖于它上面的行。似乎应该可以一次计算一行,同时遍历行?或者BigQuery不支持这种类型的窗口

如果不可能,你有什么建议

第一轮-起点

下面是BigQuery标准SQL,适用于多达3M行的我

标准SQL 创建临时函数xv FLOAT64,t INT64 返回数组 语言JSAS var i,结果=[]; 对于i=1;我 似乎应该可以一次计算一行,同时遍历行

截至2019年10月,对和的支持目前处于测试阶段

您可以提交多个用分号分隔的语句,BigQuery现在可以运行它们了

因此,从概念上讲,您的流程可能如下脚本所示:

DECLARE b_prev FLOAT64 DEFAULT NULL;
DECLARE t INT64 DEFAULT 0;
DECLARE arr ARRAY<STRUCT<t INT64, a FLOAT64, b FLOAT64>> DEFAULT [STRUCT(0, 0.0, 9.0)];

SET b_prev = 9.0 / 2;

LOOP
  SET (t, b_prev) = (t + 1, 2 * b_prev);
  IF t >= 100 THEN LEAVE;
  ELSE
    SET b_prev = CASE WHEN b_prev < 10 THEN b_prev ELSE b_prev / 6.0 END;
    SET arr = (SELECT ARRAY_CONCAT(arr, [(t, b_prev, 2 * b_prev)]));
  END IF;
END LOOP;

SELECT * FROM UNNEST(arr);
尽管上面的脚本更简单,更直接地表示非技术人员的逻辑,并且更易于管理,但它不适合需要循环100多次或更多迭代的场景。例如,上面的脚本花费了将近2分钟,而我对相同100行的原始解决方案只花费了2秒
但是对于简单/较小的情况仍然很好

BigQuery不支持迭代-但是总是有解决方法或者几乎总是-那么,您的真实数据中有多少行需要按照您描述的方式进行处理?解决方法是使用JS UDF吗;这可能是数十亿。我想到了JS UDF——但数十亿可能不符合各自的限制:oi feel,我想到了其他一些东西:哦,请继续关注——会在有空闲的时候跳进去谢谢@MikhailBerlyant——在此期间,你能给我指个方向吗?很高兴也对2天内不符合条件的问题悬赏,这对@Mikhail很有帮助。我正在努力适应我们的用例。社区感谢你的贡献。非常感谢。我能让它工作!事实上,我之前说错了。我们的表中确实有数十亿行,但每次对UDF的调用都限制在一个分区内。我们有超过100k的查询级分区,但在单个分区中,每行代表1小时。我相信需要340多年的数据才能达到这些极限。365*24*340~=3M。我发现自己在你的几个答案上拼凑出了最后的问题。虽然我还不需要锚平行技巧,但它对其他人来说是无价的&最好放在我的后口袋里。很高兴你玩得开心。接受&谢谢!
DECLARE b_prev FLOAT64 DEFAULT NULL;
DECLARE t INT64 DEFAULT 0;
DECLARE arr ARRAY<STRUCT<t INT64, a FLOAT64, b FLOAT64>> DEFAULT [STRUCT(0, 0.0, 9.0)];

SET b_prev = 9.0 / 2;

LOOP
  SET (t, b_prev) = (t + 1, 2 * b_prev);
  IF t >= 100 THEN LEAVE;
  ELSE
    SET b_prev = CASE WHEN b_prev < 10 THEN b_prev ELSE b_prev / 6.0 END;
    SET arr = (SELECT ARRAY_CONCAT(arr, [(t, b_prev, 2 * b_prev)]));
  END IF;
END LOOP;

SELECT * FROM UNNEST(arr);