在AWS Athena / Presto中在unnest和array_agg之后保留数组元素的顺序

时间:2019-08-09 06:48:49

标签: sql presto amazon-athena

我有一个雅典娜查询,该查询取消嵌套数组,将元素与另一个表联接,然后使用array_agg将它们收集回数组中。我想保留元素的原始顺序,但是Athena不支持Presto功能向ORDER BY添加array_agg子句。如何保留元素的顺序?

查询与此示例类似:

SELECT x, array_agg(b) bs
FROM table1 -- table1 columns are x, ys
CROSS JOIN UNNEST(ys) AS t(y)
JOIN table2 ON y=a -- table2 columns are a, b
GROUP BY x
  1. 默认行为似乎是保留订单。可靠吗?
  2. 如果不是(1),是否有一个实现可以保留ysbs的顺序?

3 个答案:

答案 0 :(得分:2)

也有同样的问题,我的解决方法是聚合值以常规性为键进行映射。然后将map的值转换为array(按键排序):

SELECT t1.x, 
       transform(sequence(1,cardinality(map_agg(n,y)),(x)-> map_agg(n,y)[x]) 
FROM table1 t1 CROSS JOIN 
UNNEST(t1.ys) WITH ORDINALITY AS t(y, n) JOIN
     table2 t2
     ON t1.y = t2.a
GROUP BY t1.x;

答案 1 :(得分:1)

不使用ORDER BY保留订单的一种方法:

  1. 为每个输出值添加一个排序字符串
  2. 聚合到未排序的数组
  3. 对数组进行排序
  4. 从每个数组元素中删除排序前缀
SELECT
x
-- prefix each "b" with a 19-digit sortable string
-- aggregate into array, sort, then remove the prefix
, TRANSFORM(
  ARRAY_SORT(
    array_agg(
      SUBSTR(LPAD(CAST(yi AS VARCHAR), 19, '0'), -19)
      || b))
  , e1 -> SUBSTR(e1, 1 + 19)
  ) AS bs
FROM table1 -- table1 columns are x, ys
CROSS JOIN UNNEST(ys) WITH ORDINALITY t (y, yi)
JOIN table2 ON y = a -- table2 columns are a, b
GROUP BY x

此方法假定:

  • 可排序的数据将放入varchar数组列中
  • b是字符数据(或易于转换)

答案 2 :(得分:0)

Presto支持unnest() with ordinality

SELECT t1.x, array_agg(t2.b ORDER BY n) bs
FROM table1 t1 CROSS JOIN 
     UNNEST(t1.ys) WITH ORDINALITY AS t(y, n) JOIN
     table2 t2
     ON t1.y = t2.a
GROUP BY t1.x;

请注意,您不需要注释来指定列的来源。只需使用适当的表别名对列引用进行质量检查。这也使查询变得明确且易于理解。