Aws Athena / Presto - 嵌套两个表
Aws Athena / Presto - nest two tables
我想使用 aws athena 嵌套两个镶木地板 table,这样:
Table一个
|document_id| name|
+-----------+-----+
| 1| aaa|
| 2| bbb|
Table B
| topic_id| name|document_id|
+-----------+-----+-----------+
| 1| xxx| 1|
| 2| yyy| 2|
| 3| zzz| 2|
将 table B 嵌套到 table A 中得到类似
的东西
[
{
"document_id": 1,
"name": "aaa",
"topics": [
{
"topic_id": 1,
"name": "xxx"
}
]
},
{
"document_id": 2,
"name": "bbb",
"topics": [
{
"topic_id": 2,
"name": "yyy"
},
{
"topic_id": 3,
"name": "zzz"
}
]
}
]
可能吗?有什么想法吗?
注意:我从
得到了例子
我认为可以使用 map_concat and array_agg - 但我需要将 topic_id 转换为 varchar:
with intermediate as
(
select a.document_id,a.name
,MAP(array['topic_id'], array[cast(b.topic_id as varchar)]) topic_map
,MAP(array['name'], array[b.name]) name_map
from table_a a
left join table_b b
on a.document_id = b.document_id
)
select i.document_id,i.name
,array_agg(cast(map_concat(topic_map,name_map) as json)) topics
from intermediate i
group by i.document_id,i.name;
此查询应该会为您提供所需的结果:
SELECT
a.document_id,
ARBITRARY(a.name) AS name,
ARRAY_AGG(
CAST(
ROW(topic_id, b.name)
AS ROW(topic_id INTEGER, name VARCHAR)
)
) AS topics
FROM table_a a
LEFT JOIN table_b b USING (document_id)
GROUP BY a.document_id
如果您 运行 该查询并将结果转换为 JSON 数组,您应该从您的问题中得到所需的结果。
解决方案的核心是使用 ROW
构建主题结构,并为每个文档聚合这些结构。这是雅典娜的一个令人困惑的细节; DDL 语句使用 Hive SQL,其中有一个名为 struct
的类型,而查询使用 Presto SQL,其中等效概念是 ROW
,并且它的名称无济于事整数和字符串类型也不同。在 DDL 中类型是 struct<topic_id:int,name:string>
但在 DML 中它是 ROW(topic_id INTEGER, name VARCHAR)
.
我使用 ARBITRARY
作为文档名称,但按文档 ID 和名称分组也可以,结果是一样的。
当我 运行 对你问题中的数据进行上面的查询时,我得到了这个结果:
document_id | name | topics
------------+------+-------
1 | aaa | [{topic_id=1, name=xxx}]
2 | bbb | [{topic_id=3, name=zzz}, {topic_id=2, name=yyy}]
如果您读取结果集 JSON,您应该得到您发布的内容,模数排序。
我想使用 aws athena 嵌套两个镶木地板 table,这样:
Table一个
|document_id| name|
+-----------+-----+
| 1| aaa|
| 2| bbb|
Table B
| topic_id| name|document_id|
+-----------+-----+-----------+
| 1| xxx| 1|
| 2| yyy| 2|
| 3| zzz| 2|
将 table B 嵌套到 table A 中得到类似
的东西[
{
"document_id": 1,
"name": "aaa",
"topics": [
{
"topic_id": 1,
"name": "xxx"
}
]
},
{
"document_id": 2,
"name": "bbb",
"topics": [
{
"topic_id": 2,
"name": "yyy"
},
{
"topic_id": 3,
"name": "zzz"
}
]
}
]
可能吗?有什么想法吗?
注意:我从
我认为可以使用 map_concat and array_agg - 但我需要将 topic_id 转换为 varchar:
with intermediate as
(
select a.document_id,a.name
,MAP(array['topic_id'], array[cast(b.topic_id as varchar)]) topic_map
,MAP(array['name'], array[b.name]) name_map
from table_a a
left join table_b b
on a.document_id = b.document_id
)
select i.document_id,i.name
,array_agg(cast(map_concat(topic_map,name_map) as json)) topics
from intermediate i
group by i.document_id,i.name;
此查询应该会为您提供所需的结果:
SELECT
a.document_id,
ARBITRARY(a.name) AS name,
ARRAY_AGG(
CAST(
ROW(topic_id, b.name)
AS ROW(topic_id INTEGER, name VARCHAR)
)
) AS topics
FROM table_a a
LEFT JOIN table_b b USING (document_id)
GROUP BY a.document_id
如果您 运行 该查询并将结果转换为 JSON 数组,您应该从您的问题中得到所需的结果。
解决方案的核心是使用 ROW
构建主题结构,并为每个文档聚合这些结构。这是雅典娜的一个令人困惑的细节; DDL 语句使用 Hive SQL,其中有一个名为 struct
的类型,而查询使用 Presto SQL,其中等效概念是 ROW
,并且它的名称无济于事整数和字符串类型也不同。在 DDL 中类型是 struct<topic_id:int,name:string>
但在 DML 中它是 ROW(topic_id INTEGER, name VARCHAR)
.
我使用 ARBITRARY
作为文档名称,但按文档 ID 和名称分组也可以,结果是一样的。
当我 运行 对你问题中的数据进行上面的查询时,我得到了这个结果:
document_id | name | topics
------------+------+-------
1 | aaa | [{topic_id=1, name=xxx}]
2 | bbb | [{topic_id=3, name=zzz}, {topic_id=2, name=yyy}]
如果您读取结果集 JSON,您应该得到您发布的内容,模数排序。