在 presto/athena 中按元素聚合数组

Aggregate arrays element-wise in presto/athena

我有一个 table,它有一个 array 列。保证数组的大小在所有行中都相同。是否可以对数组进行逐元素聚合以创建新数组?

例如如果我的聚合是 avg 函数,那么:

Array 1: [1,3,4,5]
Array 2: [3,5,6,1]

Output:  [2,4,5,3]

我想写这样的查询:

select
  timestamp_column,
  avg(array_column) as new_array
from 
  my_table
group by 
  timestamp_column

该数组包含将近 200 个元素,因此我不希望对查询中的每个元素进行硬编码 :)

这可以通过组合 2 个鲜为人知的 SQL 构造来完成:UNNEST WITH ORDINALITY,以及 array_agg 和 ORDER BY。

第一步是使用CROSS JOIN UNNEST(a) WITH ORDINALITY 将数组解压成行。对于每个数组中的每个元素,它将输出一行,其中包含元素值和该元素在数组中的位置。

然后在序数上使用标准 GROUP BY,在值上使用 sum

最后,您使用 array_agg(value_sum ORDER BY ordinal) 将总和重新组装回数组。此表达式的关键部分是 array_agg 调用中的 ORDER BY 子句。没有这个,值将是任意顺序。

这是一个完整的例子:

WITH t(a) AS (VALUES array [1, 3, 4, 5], array [3, 5, 6, 1])
SELECT array_agg(value_sum ORDER BY ordinal)
FROM (
    SELECT ordinal, sum(value) AS value_sum
    from t
             CROSS JOIN UNNEST(t.a) WITH ORDINALITY AS x(value, ordinal)
    GROUP BY ordinal);