如何在 BigQuery SQL 中添加数组?

Posted

技术标签:

【中文标题】如何在 BigQuery SQL 中添加数组?【英文标题】:How do I add arrays in BigQuery SQL? 【发布时间】:2019-05-06 12:22:33 【问题描述】:

我有一个 UDF,它为表的每一行返回一个大小相同的浮点数组。如何对这些数组的值求和?

换句话说,我该怎么做这样的事情:

create temp function f(...)
returns array<float64>
...;
select sum(f(column)) from table

作为此操作的结果,我需要获得另一个相同大小的 array,其中

result[i] = sum(over rows) f(row, column)[i]

【问题讨论】:

一些输入/期望的输出总是有助于理解你想要做什么:) @hlagos 现有的 BigQuery SUM() 聚合函数不适用于数组。所以我想知道是否有一些技巧可以完成这项工作。 【参考方案1】:

这是一个使用 ANY TYPE 的函数,以支持对 FLOAT64INT64NUMERIC 的数组求和以及一些示例输入:

CREATE TEMP FUNCTION ElementWiseSum(arr1 ANY TYPE, arr2 ANY TYPE) AS (
  ARRAY(SELECT x + arr2[OFFSET(off)] FROM UNNEST(arr1) AS x WITH OFFSET off ORDER BY off)
);

SELECT arr1, arr2, ElementWiseSum(arr1, arr2) AS result
FROM (
  SELECT [1, 2, 3] AS arr1, [4, 5, 6] AS arr2 UNION ALL
  SELECT [7, 8], [9, 10] UNION ALL
  SELECT [], [] UNION ALL
  SELECT [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]
);

它使用WITH OFFSET 取消嵌套arr1,然后使用此偏移量从arr2 检索等效元素,并按偏移量排序以确保保留元素顺序。

编辑:要跨行求和,您可以取消嵌套数组,计算按元素偏移量分组的总和,然后将总和重新聚合到一个新数组中:

SELECT
  ARRAY_AGG(sum ORDER BY off) AS arr
FROM (
  SELECT
    off,
    SUM(x) AS sum
  FROM (
    SELECT [1, 2, 3] AS arr UNION ALL
    SELECT [7, 8, 9] UNION ALL
    SELECT [4, 5, 6] UNION ALL
    SELECT [10, 11, 12]
  ), UNNEST(arr) AS x WITH OFFSET off
  GROUP BY off
);

【讨论】:

感谢@Elliot Brossard。请给我一个提示,我如何使用这种方法从我的表中的 20000 行中对我的 UDF 返回的 20000 个数组求和? 我误解了你在问什么。看看这个修改是否有帮助。 是的,@Elliot Brossard。我明白了。我想知道这种“unnest/sum/group by offset”方法是否会扩展到数组大小~10K?我将不得不对其进行测试。 数组的大小有 100 MB 的限制,但如果你的意思是你有 10K 个不同的数组,那么是的,应该没问题。 我的情况是在 10-100K 行的范围内,每行生成一个数组,比如说,10K 元素,我想对这 10-100K 数组求和,结果将是一个10K 元素数组。 @Elliot Brossard【参考方案2】:

因此,根据您的评论,您正在寻找的是 sum 您所有数组的值。这就是使用UNNEST 运算符的方法

WITH mydata  AS (
  SELECT [1.4, 1.3, 1.4, 1.1] as myarray
  union all 
  SELECT [1.4, 1.3, 1.4, 1.1] as myarray
  union all 
  SELECT [1.4, 1.3, 1.4, 1.1] as myarray
)

SELECT SUM(eachelement) from mydata, UNNEST(myarray) AS eachelement; 

【讨论】:

谢谢@hlagos,但这不是我想要的。你的建议给了我一个标量。我正在寻找一种方法来获得一个按元素求和的数组:[4.2, 3.9, 4.2, 3.3]。【参考方案3】:

如果您定义了 UDF(接受您的列并返回一个预先确定(或固定)维度的 float64 数组),您可以使用简化的解决方案。例如,在 3-d 数组的情况下,类似于:

create temp function f(...)
returns array<float64>
...;

with dataset as (
  select arr[offset(0)] as col_a, arr[offset(1)] as col_b, arr[offset(2)] as col_c
    from (
       select f(mycolumn) as arr
       from `mydataset.mytable`
    )
)

select [sum(col_a), sum(col_b), sum(col_c)] as new_array from dataset

【讨论】:

谢谢@khan。我考虑了一下,但我拥有的数组大约有 10K 长。 你的意思是这些是 10k 维数组?【参考方案4】:

这并没有直接回答 OP 的问题,而是人们登陆此页面搜索“如何在 BigQuery SQL 中添加数组?”可能会受益。

(基于@elliott-brossard 回答编辑)如果您有 2 个数组,但 1 个数组包含一个结构,您可以使用以下代码将它们添加在一起:

WITH mydata AS (
  SELECT
    [1, 2, 3] AS arr
    -- ,[7, 8, 9] AS arr2
    ,[
      STRUCT(7 AS timeOnSite)
      ,STRUCT(8 AS timeOnSite)
      ,STRUCT(9 AS timeOnSite)
    ] AS arr2
)

SELECT
  (
    SELECT
      ARRAY_AGG(sum ORDER BY off) AS arr
    FROM (
      SELECT
        off,
        SUM(x) AS sum
      FROM (
        SELECT arr UNION ALL
        -- SELECT arr2
        SELECT (SELECT ARRAY_AGG(t.timeOnSite) FROM UNNEST(arr2) AS t)
      ), UNNEST(arr) AS x WITH OFFSET off
      GROUP BY off
    )  
  ) AS sum_arrays
FROM 
  mydata

【讨论】:

以上是关于如何在 BigQuery SQL 中添加数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 BigQuery 标准 SQL 中取消嵌套多个数组

在 Bigquery 中,如何使用标准 Sql 过滤 Struct 数组以匹配 Struct 中的多个字段?

如何比较标准 SQL(BigQuery)中的两个数组?

如何在 BigQuery 上展开数组以将列添加到现有表

如何在 ReDash 中设置标准 SQL BigQuery

如何使用 SQL (BigQuery) 计算 TF/IDF