双嵌套 array_agg(row_to_json())
Double nested array_agg(row_to_json())
我有三个表:人,宠物,小狗。
一个人可以养很多只宠物。
一只宠物可以养很多只小狗。
我构建我的架构并插入数据,如下所示:
create table person (
id serial primary key,
name text
);
create table pet (
id serial primary key,
owner int,
name text
);
create table pup (
id serial primary key,
parent int,
name text
);
insert into person (name) values
('tom'), ('dick'), ('harry');
insert into pet (owner, name) values
(1, 'fluffy'),
(2, 'snuffles'),
(1, 'mr potato head');
insert into pup (parent, name) values
(1, 'fluffy jr'),
(1, 'fluffy II');
我们看到“tom”这个人有两只宠物“fluffy”和“mr potato head”。
我们看到人“dick”有一只宠物“snuffles”。
我们看到宠物“fluffy”有两只幼崽“fluffy jr”和“fluffy II”。
我想得到一个双层嵌套数组,但我只能得到一层嵌套。这是我的 sql fiddle - http://sqlfiddle.com/#!17/03659/2 他们查询我使用:
select p.*,
array_agg(row_to_json(
pet
)) filter (where pet.id is not null) as pets
from person p
left outer join pet pet
on pet.owner = p.id
group by p.id;
我希望的是为“pups”双重嵌套输入“tom”:
{
"id": 1,
"name": "tom",
{
"id": 1,
"owner": 1,
"name": "fluffy",
"pups": [
{
"id": 1,
"parent": 1,
"name": "fluffy jr"
},
{
"id": 2,
"parent": 1,
"name": "fluffy II"
}
]
}
}
有人知道如何获得这种双重嵌套吗?
您可以在子查询中按 parent 聚合“小狗”,然后在外部查询中按人聚合:
select pn.*,
jsonb_agg(jsonb_build_object(
'id', pt.id,
'owner', pt.owner,
'name', pt.name,
'pups', pp.pups
)) filter(where pt.id is not null) pets
from person pn
left join pet pt
on pt.owner = pn.id
left join (select parent, jsonb_agg(pp) pups from pup pp group by parent) pp
on pp.parent = pt.id
group by pn.id;
请注意,这使用 JSON 聚合函数 json[b]_agg()
生成 JSON 数组而不是 array_agg()
。我也从 json
切换到 jsonb
- 后者应该是首选,因为它提供了比前者更多的功能。
我有三个表:人,宠物,小狗。
一个人可以养很多只宠物。 一只宠物可以养很多只小狗。
我构建我的架构并插入数据,如下所示:
create table person (
id serial primary key,
name text
);
create table pet (
id serial primary key,
owner int,
name text
);
create table pup (
id serial primary key,
parent int,
name text
);
insert into person (name) values
('tom'), ('dick'), ('harry');
insert into pet (owner, name) values
(1, 'fluffy'),
(2, 'snuffles'),
(1, 'mr potato head');
insert into pup (parent, name) values
(1, 'fluffy jr'),
(1, 'fluffy II');
我们看到“tom”这个人有两只宠物“fluffy”和“mr potato head”。 我们看到人“dick”有一只宠物“snuffles”。
我们看到宠物“fluffy”有两只幼崽“fluffy jr”和“fluffy II”。
我想得到一个双层嵌套数组,但我只能得到一层嵌套。这是我的 sql fiddle - http://sqlfiddle.com/#!17/03659/2 他们查询我使用:
select p.*,
array_agg(row_to_json(
pet
)) filter (where pet.id is not null) as pets
from person p
left outer join pet pet
on pet.owner = p.id
group by p.id;
我希望的是为“pups”双重嵌套输入“tom”:
{
"id": 1,
"name": "tom",
{
"id": 1,
"owner": 1,
"name": "fluffy",
"pups": [
{
"id": 1,
"parent": 1,
"name": "fluffy jr"
},
{
"id": 2,
"parent": 1,
"name": "fluffy II"
}
]
}
}
有人知道如何获得这种双重嵌套吗?
您可以在子查询中按 parent 聚合“小狗”,然后在外部查询中按人聚合:
select pn.*,
jsonb_agg(jsonb_build_object(
'id', pt.id,
'owner', pt.owner,
'name', pt.name,
'pups', pp.pups
)) filter(where pt.id is not null) pets
from person pn
left join pet pt
on pt.owner = pn.id
left join (select parent, jsonb_agg(pp) pups from pup pp group by parent) pp
on pp.parent = pt.id
group by pn.id;
请注意,这使用 JSON 聚合函数 json[b]_agg()
生成 JSON 数组而不是 array_agg()
。我也从 json
切换到 jsonb
- 后者应该是首选,因为它提供了比前者更多的功能。