Google bigquery 将带变量的循环转换为BigQuery SQL

Google bigquery 将带变量的循环转换为BigQuery SQL,google-bigquery,Google Bigquery,我有数千个脚本,其中包括循环数据集,并使用变量进行累加。例如: // assuming that 'ids' is populated from some BQ table ids = [1, 2, 3, 4, 5] var1 = "v1" //initialize variable var2 = "v2" //initialize variable for id in ids var1 = var2 if (id > 2) var2 = var1 +

我有数千个脚本,其中包括循环数据集,并使用变量进行累加。例如:

// assuming that 'ids' is populated from some BQ table
ids = [1, 2, 3, 4, 5]
var1 = "v1"   //initialize variable
var2 = "v2"   //initialize variable

for id in ids
    var1 = var2
    if (id > 2)
      var2 = var1 + "-" + item
    else
      var2 = id
    print(id, var1, var2)
这将产生以下输出:

1,v2,1
2,1,2
3,2,2-3
4,2-3,2-3-4
5,2-3-4,2-3-4-5
其他几点需要考虑:

  • 脚本可以包含n个变量
  • 变量可以充当 累加器或可仅具有文字
  • 循环中的条件可以是 更复杂的,多个嵌套的
    if
    /
    else
    条件
  • 脚本也可以有嵌套循环,该循环将循环n次或直到不满足特定条件为止
可以在BigQuery SQL中支持它吗?我也支持BigQueryUDF,但UDF不支持可变状态

此外,由于有数千个这样的脚本,我不想手动执行,而是想自动转换。解析这些脚本对我来说不是问题,我只需要将其转换为等效的BigQuery SQL。让我知道如何解决这个问题

编辑:
虽然我更倾向于使用纯SQL方法,但似乎也是一个很有前途的选择。

我已经在BigQuery中使用SQL UDF复制了您的脚本,我使用了标准SQL而不是传统SQL,您可以阅读更多有关它的信息。我想声明UDF支持JavaScript,我发现使用它的功能编写它更好

我使用此虚拟数据而不是声明数组:

下面是我开发的脚本,用于重现您使用代码完成的内容

DECLARE VAR1 STRING DEFAULT 'v1';
DECLARE var2 STRING DEFAULT 'v2';

CREATE TEMPORARY FUNCTION test_v2 ( x1 string , x2 string,id INT64)
RETURNS STRING
LANGUAGE js AS """
var output= new Array(); 
i =0;
          while(i <= 5){
          x1=x2;
          if(i > 2) {
            x2 =x1 + " - " + i ;
            output.push(x2);

          } else{
                  x2 = i;
                  output.push(x2);
                } 
          i++;}return  output[id];
""";

CREATE TEMPORARY FUNCTION test_v1 ( x1 string , x2 string,id INT64)
RETURNS STRING
LANGUAGE js AS """
var output= new Array(); 
i =1;
output.push(x1);
          while(i <= 5){
          x1 = x2;
          if(i > 2) {
            x2 =x1 + " - " + i ;
            output.push(x1);

          } else{
                  output.push(x1);
                  x2 = i;
                } 
          i++;}return  output[id];
""";

SELECT ids,test_v1(var1,var2,ids) as v1, test_v2(var1,var2,ids) as var2 FROM `test-proj-261014.sample.ids` LIMIT 1000
声明VAR1字符串默认值为“v1”;
声明var2字符串默认值为“v2”;
创建临时功能测试_v2(x1字符串,x2字符串,id INT64)
返回字符串
语言js为“”
var输出=新数组();
i=0;
而(i)(2){
x2=x1+“-”+i;
输出推力(x2);
}否则{
x2=i;
输出推力(x2);
} 
i++;}返回输出[id];
""";
创建临时功能测试_v1(x1字符串,x2字符串,id INT64)
返回字符串
语言js为“”
var输出=新数组();
i=1;
输出推力(x1);
而(i)(2){
x2=x1+“-”+i;
输出推力(x1);
}否则{
输出推力(x1);
x2=i;
} 
i++;}返回输出[id];
""";
从'test-proj-261014.sample.ids'限制1000中选择ID,test_v1(var1,var2,ids)作为v1,test_v2(var1,var2,ids)作为var2
请注意,我必须编写两个不同的函数,分别为var1和var2行编写一个函数。此外,阵列从test_v1功能中的位置1开始

最后,结果是:


我希望它能有所帮助。

我能够为上述示例脚本转换SQL查询:

with  t as
(select 1 as id union all
select 2 as id union all
select 3 as id union all
select 4 as id union all
select 5 as id)

select id, if(id = 1, 'v2', lag(var2) over(order by id)) var1, var2
from (
    select
      id,
      if(
        id > 2,
        string_agg(if(id > 1, concat('', '', cast(id as string)), null), '-') over (rows between unbounded preceding and current row),
        cast(id as string)
      ) var2
    from t
  )

像这样,我也能够转换纯SQL中的大多数脚本。它只是围绕它构建模型,涉及面更广,但至少我正在进行手动转换。

你看过Bigquery吗?是的,我看过。请参阅编辑部分。我的主要目标是只使用SQL,但如果不可能的话,我也可以使用脚本。到目前为止,我还不能用SQL重现您的案例,我相信最好的选择是使用UDF。@AlexandreMoraes您能用一个例子说明如何使用UDF获得类似的结果吗?据我所知,UDF应该是无状态的,我无法让它工作。还有关于我提到的其他挑战的想法吗?当然,我以一个虚拟表为例,成功地获得了所需的输出,这可能有助于澄清您的问题。关于其他问题,你能更具体一点吗?我认为最好一次解决一个问题。我可以发布我写的脚本作为答案。这对我的情况没有帮助,因为我不知道预先输入数据的大小。除此之外,我认为这也会对性能产生影响,因为每次记录迭代都会发生n次。我上传了语法,以澄清如何将代码转换为BigQuery,而不是整数5,您可以使用“id”。此外,关于迭代,您可以使用循环中断并引用要使用的数组上的位置(可能是“id”)。此外,我鼓励您查看。注意emit参数,它包含一行输出数据。