Я не мог понять, как я могу получить иерархический объект из запроса json.
Мой пример данных:
CREATE TABLE
"postgres"."public"."owner"
(
owner_id INTEGER,
name text,
mail text
)
;
insert into owner (owner_id, name, mail) values
(1, 'Owner1', 'mail@owner1.do.main'),
(2, 'Owner2', 'mail@owner2.do.main')
;
CREATE TABLE
"postgres"."public".ip
(
owner_id INTEGER,
status text,
ip inet,
host text
)
;
insert into ip (owner_id, status, ip, host) values
(1, 'active', '12.34.56.78', 'host78.owner1.do.main'),
(1, 'active', '12.34.56.79', 'host79.owner1.do.main'),
(1, 'active', '12.34.56.80', 'host80.owner1.do.main'),
(1, 'tests failed', '12.34.56.81', 'host81.owner1.do.main'),
(1, 'tests failed', '12.34.56.82', 'host82.owner1.do.main'),
(2, 'active', '34.56.78.1', 'host1.owner2.do.main'),
(2, 'active', '34.56.78.2', 'host2.owner2.do.main'),
(2, 'not listed', '34.56.78.3', 'host3.owner2.do.main'),
(2, 'not listed', '34.56.78.4', 'host4.owner2.do.main')
;
Моя предполагаемая структура:
{
"Owner1": {
"mail": "mail@owner1.do.main",
"ips": {
"active": {
"12.34.56.78": "host78.owner1.do.main",
"12.34.56.79": "host79.owner1.do.main",
"12.34.56.80": "host80.owner1.do.main"
},
"tests failed": {
"12.34.56.81": "host81.owner1.do.main",
"12.34.56.82": "host82.owner1.do.main"
}
}
},
"Owner2": {
"mail": "mail@owner2.do.main",
"ips": {
"active": {
"34.56.78.1": "host1.owner2.do.main",
"34.56.78.2": "host2.owner2.do.main"
},
"not listed": {
"34.56.78.3": "host3.owner2.do.main",
"34.56.78.4": "host4.owner2.do.main"
}
}
}
}
После долгих попыток я пришел к следующему запросу:
select json_object_agg(name, status_ips)
from (
select name, json_build_object('mail', mail, 'ips', json_object_agg(status, ips)) as status_ips
from (
select owner_id, status, json_object_agg(ip, host) as ips
from ip
group by owner_id, status
) IPS
join owner
using (owner_id)
group by name, mail
) OWNER_IPS;
Поскольку у меня есть 2 подзапроса, мой вопрос: это слишком сложно? Есть ли лучшие способы получить мой результат?