给出 Athena 中的原始表格,类似于下面这个人为的示例:
原表:
a | b | cms消息 | c |
---|---|---|---|
... | ... | {"asset": {"metadata": {"item": [{"key": "author", "value": "Rob"}, { "key": "id", "value": "123 "}, {"key": "version", "value": "1"}]}}} | ... |
... | ... | {“资产”:{“元数据”:{“项目”:[{“键”:“id”,“值”:“456”},{“键”:“作者”,“值”:“约翰"}, {"key": "version", "value": "3"}]}}} | ... |
... | ... | {"asset": {"metadata": {"item": [{"key": "version", "value": "2"}, {"key": "author", "value": "Sally "}, {"key": "id", "value": "789" }]}}} | ... |
我正在尝试从
cmsmessage
列中的字符串化 JSON 创建一个视图:
所需的结果视图:
id | 作者 | 版本 |
---|---|---|
123 | 罗布 | 1 |
456 | 约翰 | 3 |
789 | 莎莉 | 3 |
正如您在“所需结果视图”中看到的那样我本质上是想根据
item
值的值从key
数组的每个对象中提取数据。
[{"key": "author", "value": "Rob"}, { "key": "id", "value": "123"}, {"key": "version", "value": "1"}]
我已经看到/尝试过通过索引访问数组中的项目的各种示例,例如
[0]
例如 Athena 文档中的 示例。但是,鉴于原始表的 cmsmessage
列中的 json/字符串,数组中的索引位置可能会有所不同。
我失败的尝试:
下面显示了我失败的尝试:
WITH dataset AS
(
SELECT *
FROM (VALUES
('{"asset": {"metadata": {"item": [{"key": "author", "value": "Rob"}, { "key": "id", "value": "123"}, {"key": "version", "value": "1"}]}}}'),
('{"asset": {"metadata": {"item": [{ "key": "id", "value": "456"}, {"key": "author", "value": "John"}, {"key": "version", "value": "3"}]}}}'),
('{"asset": {"metadata": {"item": [{"key": "version", "value": "2"}, {"key": "author", "value": "Sally"}, {"key": "id", "value": "789" }]}}}')
) AS t (cmsmessage)
)
SELECT
json_extract_scalar(objArray, '$.key') as _keys,
json_extract_scalar(objArray, '$.value') as _values
FROM dataset
CROSS JOIN UNNEST(CAST(json_extract(cmsmessage, '$.asset.metadata.item') as array(json))) as t (objArray)
json_query
,它对 JSON 路径语法有更好的支持:
SELECT json_query(cmsmessage, 'lax $.asset.metadata.item[*]?(@.key=="id").value') AS id
, json_query(cmsmessage, 'lax $.asset.metadata.item[*]?(@.key=="author").value') AS author
, json_query(cmsmessage, 'lax $.asset.metadata.item[*]?(@.key=="version").value') AS version
FROM dataset;
应该适用于基于 Trino 的 Athena 引擎版本 3。
对于版本 2,您可以通过数组操作实现类似的效果。