如何在 BigQuery 中逐个元素地聚合数组?

Posted

技术标签:

【中文标题】如何在 BigQuery 中逐个元素地聚合数组?【英文标题】:How to aggregate arrays element by element in BigQuery? 【发布时间】:2021-03-29 05:34:48 【问题描述】:

在 BigQquery 中,如何逐个元素地聚合数组?

例如,如果我有这张桌子

id array_value
1 [1, 2, 3]
2 [4, 5, 6]
3 [7, 8, 9]

我想对所有向量元素求和并输出[1+4+7, 2+5+8, 3+6+9] = [12, 15, 18]

我可以使用 SELECT SUM(float_field) FROM table 对浮点字段求和,但是当我尝试将 SUM 应用于数组时,我得到了

参数类型的聚合函数 SUM 没有匹配的签名:ARRAY。 支持的签名:SUM(INT64);总和(FLOAT64);总和(数字); SUM(BIGNUMERIC) 在 [1:8]

我在文档中找到了ARRAY_AGG,但这不是我想要的:它只是从值创建一个数组。

【问题讨论】:

【参考方案1】:

以下是 BigQuery 标准 SQL

select array_agg(val order by offset) 
from (
  select offset, sum(val) as val 
  from `project.dataset.table` t, 
  unnest(array_value) as val with offset 
  group by offset
)    

【讨论】:

【参考方案2】:

我认为从技术上讲,您只需使用 offset()safe_offset() 引用数组中的各个值,以防可能缺少值

-- example data
with temp as (
  select * from unnest([
    struct(1 as id, [1, 2, 3] as array_value),
    (2, [4,5,6]),
    (3, [7,8])
  ])
)

-- actual query
select
  [
    SUM( array_value[safe_offset(0)] ),
    SUM( array_value[safe_offset(1)] ),
    SUM( array_value[safe_offset(2)] )
  ] as result_array
from temp

我将它们放在结果数组中,但您不必这样做。我让最后一个数组缺少一个值,以表明查询没有中断。如果你想让它崩溃,你应该使用offset() 而不使用'safe_'

【讨论】:

如何将其推广到大数组,比如说 1000 个值?我不想手动编写 1000 个索引 我使用电子表格半自动地使用公式编写这类查询部分;)因为您基本上将这些数组条目用作列,而 SQL 不提供批量或聚合函数对于跨列,只有行,我认为不可能使用 SQL 来扩展它。您还可以在 python/etc 中编写自定义的查询构建器。 ...【参考方案3】:

我想你想要:

select array_agg(sum_val order by id) as res
from (
    select idx, sum(val) as sum_val
    from mytable t
    cross join unnest(t.array_value) as val with offset as idx
    group by idx
) t

【讨论】:

【参考方案4】:

我想你想要:

select array_agg(sum_val)
from (select (select sum(val)
              from unnest(t.array_value) val
             ) as sum_val
      from t
     ) x

【讨论】:

以上是关于如何在 BigQuery 中逐个元素地聚合数组?的主要内容,如果未能解决你的问题,请参考以下文章

在 bigquery 中聚合列并构建数组

如何在 C++ 中逐个元素地比较两个向量的相等性?

如何在 BigQuery 中从 firestore 导出的数组中查找元素

如何在 Google BigQuery 中的数组中的元素上创建表连接

如何计算 bigquery 数组字段中元素的频率

如何在JNI中比较两个jbyteArray?