雅典娜/普雷斯托:复杂的结构/阵列

时间:2019-07-16 11:08:48

标签: sql json presto amazon-athena unnest

想想我在这里问不可能的事,但把它扔在那里。 尝试在Athena中查询一些json。 我正在使用的数据如下(摘录)

condition={
        "foranyvalue:stringlike":{"s3:prefix":["lala","hehe"]},
        "forallvalues:stringlike":{"s3:prefix":["apples","bananas"]
}

..我需要到达这里: enter image description here

...加号:密钥名称不固定,所以有一天我可能会得到:

condition={"something not seen before":{"surprise":["haha","hoho"]}}

关于最后一点,我希望将其视为一个数组,并首先将“ foranyvalue”和“ forallvalues”部分拆分为单独的行。 但所有内容都用{}包裹起来,它拒绝嵌套。

但是,尽管上述计划失败了,但仍感激收到以任何方式解决此问题的任何提示!

谢谢

1 个答案:

答案 0 :(得分:0)

如果您的JSON数据没有易于描述的架构,则可以使用STRING作为列的类型,然后结合使用Athena / Presto的JSON functions来查询它们并投射到MAPUNNEST上以使结构变平。

实现我认为您要完成的目标的一种方法是:

WITH the_table AS (
  SELECT CAST(condition AS MAP(VARCHAR, JSON)) AS condition
  FROM (
    VALUES
    (JSON '{"foranyvalue:stringlike":{"s3:prefix":["lala","hehe"]},"forallvalues:stringlike":{"s3:prefix":["apples","bananas"]}}'),
    (JSON '{"something not seen before":{"surprise":["haha","hoho"]}}')
  ) AS t (condition)
),
first_flattening AS (
  SELECT 
    SPLIT(first_level_key, ':', 2) AS first_level_key,
    CAST(first_level_value AS MAP(VARCHAR, JSON)) AS first_level_value
  FROM the_table
  CROSS JOIN UNNEST (condition) AS t (first_level_key, first_level_value)
),
second_flattening AS (
  SELECT
    first_level_key,
    second_level_key,
    second_level_value
  FROM first_flattening
  CROSS JOIN UNNEST (first_level_value) AS t (second_level_key, second_level_value)
)
SELECT
 first_level_key[1] AS "for",
 TRY(first_level_key[2]) AS condition,
 second_level_key AS "left",
 second_level_value AS "right"
FROM second_flattening

我已经在第一个CTE中包含了您作为内联VALUES列表给出的两个示例,以及在表声明中到底要做什么(即,要使用的列的类型)以及要执行的处理查询(即转换)中的内容取决于您的数据以及您希望/如何设置表格。 YMMV。

该查询通过几个单独的步骤展平JSON结构,首先展平第一级键和值,然后展平内部文档的键和值。一步就可以做到,但至少要两步才能做到。

由于第一级键并不总是带有冒号,因此我使用TRY来确保访问第二个值不会破坏任何内容。您可能会更早地过滤掉没有冒号的值,并避免这种情况,因为您对它们不感兴趣。