Presto unnest json

Posted

技术标签:

【中文标题】Presto unnest json【英文标题】: 【发布时间】:2016-04-02 11:55:44 【问题描述】:

关注这个问题:how to cross join unnest a json array in presto

我尝试运行提供的示例,但是 我这样做时出错了

SQL 命令:

select x.n
from
unnest(cast(json_extract('"payload":["type":"b","value":"9", 
"type":"a","value":"8"]','$.payload') as array<varchar>)) as  x(n)

我得到的错误:

Value cannot be cast to array<varchar> java.lang.RuntimeException: java.lang.NullPointerException: string is null

【问题讨论】:

【参考方案1】:

SELECT JSON_EXTRACT('"payload":["type":"b","value":"9", "type":"a","value":"8"]','$.payload')

给予:

["type":"b","value":"9", "type":"a","value":"8"]

这是ARRAY&lt;MAP&lt;VARCHAR,VARCHAR&gt;&gt;。 您可以将查询更改为: SELECT x.n FROM UNNEST (CAST(JSON_EXTRACT('"payload":["type":"b","value":"9","type":"a","value":"8"]','$.payload') AS ARRAY<MAP<VARCHAR, VARCHAR>>)) AS x(n)

【讨论】:

我运行了你的建议,它似乎部分有效。为了分离地图的值,我必须明确选择地图的值:`SELECT xn['type']as "type",xn['value']as "value" FROM UNNEST (CAST(JSON_EXTRACT(' "有效载荷":["type":"b","value":"9","type":"a","value":"8"]','$.payload') AS ARRAY>)) AS x(n)` 是否有替代的直接方法? 另一种选择,您可以像这样使用 x(type,value) ::: SELECT type, value FROM UNNEST(CAST(JSON_EXTRACT( '"payload":[ "type":"b","value":"9","type":"a","value":"8"]' ,'$.payload' ) as ARRAY(ROW( type VARCHAR, value VARCHAR)) ) ) as x(type,value);【参考方案2】:

返回数据类型的一种可能解释如下:

ARRAY<MAP<VARCHAR,VARCHAR>>

但缺点是无法使用点表示法访问地图中的值。

另一种假设的数据类型是:

ARRAY(ROW(type VARCHAR, value VARCHAR))

类似于 ARRAY&lt;STRUCT&lt; Hive 数据类型等效项。

这里有很多题外话>> JSON 有点模棱两可。

哪一个是正确的? JSON 对象是映射的表示(哈希图、字典、键值对,无论您的语言如何称呼它)还是更像一个结构(对象、类、名称属性包,无论您的语言如何称呼)?它起源于 javascript(对象表示法),旨在满足数组、对象和原始类型的需求,但更广泛的使用意味着它在其他语言中具有模棱两可的映射 (ha)。也许在功能上等效,但理论上MAP 对于随机读/写应该更快,ROW 可能有一些额外的面向对象的开销,但这都是在 Java 中实现的,反正一切都是对象,所以我没有答案。使用任何你喜欢的东西。

您发现这有点冗长:

SELECT 
x.n['type'] as "type",
x.n['value'] as "value"
FROM UNNEST (
            CAST(
                JSON_EXTRACT('"payload":["type":"b","value":"9","type":"a","value":"8"]'
                             ,'$.payload') 
                AS ARRAY<MAP<VARCHAR, VARCHAR>>
                )
            ) 
        AS x(n)

这是另一种选择

SELECT
    n.type,
    n.value
FROM UNNEST(
            CAST(
                JSON_EXTRACT(
                            '"payload":["type":"b","value":"9","type":"a","value":"8"]'
                            ,'$.payload'
                            ) 
                as ARRAY(ROW(type VARCHAR, value VARCHAR))
                )
            ) as x(n)

同样冗长;列的名称只是转移到 CAST 表达式,但可能(主观!)更容易查看。

【讨论】:

【参考方案3】:

您可以对各个列使用 JSON_EXTRACT、CAST 和最后的 UNNEST

SELECT type,value FROM 
UNNEST(CAST(JSON_EXTRACT('"payload":["type":"b","value":"9", 
                          "type":"a","value":"8"]'
                         ,'$.payload'
                 ) as ARRAY(ROW(type VARCHAR, value VARCHAR)
            )
       )
) as x(type,value)

输出如下

 type | value
------+-------
 b    | 9
 a    | 8

【讨论】:

以上是关于Presto unnest json的主要内容,如果未能解决你的问题,请参考以下文章

Presto unnest json

UNPIVOT 一个 presto 表

Oracle调优之no_unnest和unnest用法简介

BigQuery:使用 UNNEST 检查数组的内容

unnest_tokens 及其错误(“”)

Google Bigquery 外部加入 UNNEST