如何在 Presto 中交叉加入取消嵌套 JSON 数组
Posted
技术标签:
【中文标题】如何在 Presto 中交叉加入取消嵌套 JSON 数组【英文标题】:How to cross join unnest a JSON array in Presto 【发布时间】:2015-07-08 02:27:33 【问题描述】:给定一个包含如下 JSON 列的表:
"payload":["type":"b","value":"9", "type":"a","value":"8"]
"payload":["type":"c","value":"7", "type":"b","value":"3"]
如何编写一个 Presto 查询来为我提供所有条目的平均 b
值?
到目前为止,我认为我需要使用 Hive 的 lateral view explode 之类的东西,它的等价物是 Presto 中的 cross join unnest。
但我不知道如何为 cross join unnest
编写 Presto 查询。
如何使用cross join unnest
展开所有数组元素并选中它们?
【问题讨论】:
【参考方案1】:这是一个例子
with example(message) as (
VALUES
(json '"payload":["type":"b","value":"9","type":"a","value":"8"]'),
(json '"payload":["type":"c","value":"7", "type":"b","value":"3"]')
)
SELECT
n.type,
avg(n.value)
FROM example
CROSS JOIN
UNNEST(
CAST(
JSON_EXTRACT(message,'$.payload')
as ARRAY(ROW(type VARCHAR, value INTEGER))
)
) as x(n)
WHERE n.type = 'b'
GROUP BY n.type
with
定义了一个名为 example
的公用表表达式 (CTE),其列别名为 message
VALUES
返回逐字表行集
UNNEST
在单行的列中获取一个数组,并将该数组的元素作为多行返回。
CAST
正在将JSON
类型更改为UNNEST
所需的ARRAY
类型。它可能很容易成为 ARRAY<MAP<
,但我发现 ARRAY(ROW(
更好,因为您可以指定列名,并在 select 子句中使用点表示法。
JSON_EXTRACT
正在使用 jsonPath 表达式返回 payload
键的数组值
avg()
和group by
应该是熟悉的 SQL。
【讨论】:
问题指定了 Presto,但是如果使用 Athena,它似乎转换为ARRAY(ROW(
并且不支持其他一些复杂类型,因此请改用 ARRAY(MAP(VARCHAR,VARCHAR))
并在 select 和 group by 子句中参考x.n['type']
等值【参考方案2】:
正如您所指出的,这最终在 Presto 0.79 中实现。 :)
下面是here 的转换语法示例:
select cast(cast ('[1,2,3]' as json) as array<bigint>);
特别忠告,Presto 中没有像 Hive 中那样的“字符串”类型。 这意味着如果您的数组包含字符串,请确保您使用类型“varchar”,否则您会收到一条错误消息,提示“类型数组不存在”,这可能会产生误导。
select cast(cast ('["1","2","3"]' as json) as array<varchar>);
【讨论】:
值不能转换为数组(varchar)【参考方案3】:问题是我运行的是旧版本的 Presto。
unnest
在 0.79 版本中添加
https://github.com/facebook/presto/blob/50081273a9e8c4d7b9d851425211c71bfaf8a34e/presto-docs/src/main/sphinx/release/release-0.79.rst
【讨论】:
以上是关于如何在 Presto 中交叉加入取消嵌套 JSON 数组的主要内容,如果未能解决你的问题,请参考以下文章