Reputation: 564
I am trying to create json object from getting some info from one table, then creating interger arrays from some other tables' id's and adding n > 1
(2 or more) arrays to the json object. I am using Postgres version 10.7:
select json_build_object(
'id', bi.id,
'street', ba.street,
'features1', features1.f1_json_arr,
'features2', features2.f2_json_arr
)
from business.info bi
inner join business.address ba on bi.id = ba.location_id
left outer join (
select f1.location_id,
json_agg(f1_id) as f1_json_arr
from business.features1 as f1
group by f1.location_id
) features1 on bi.id = features1.location_id
left outer join (
select f2.location_id,
json_agg(f2_id) as f2_json_arr
from business.feature2 as f2
group by f2.location_id
) features2 on bi.id = features2.location_id
where bi.id='1234';
which gives me a result as I want, like so:
{
"id": "1234",
"street", "some street",
"features1": [
2,
1
],
"features2": [
3,
2,
1
]
}
Is there a cleaner way to do this? I tried this:
select json_build_object(
'id', bi.id,
'street', ba.street_name,
'features1', f1_and_f2.f1_json_arr,
'features2', f1_and_f2.f2_json_arr
)
from business.info bi
inner join business.address ba
on bi.id = ba.location_id
left outer join (
select f1.location_id,
json_agg(f1_id) as f1_json_arr,
json_agg(f2_id) as f2_json_arr
from business.feature1 as f1
inner join business.feature2 as f2 on f1.location_id = f2.location_id
group by f1.location_id
) f1_and_f2 on bi.id = f1_and_f2.location_id
where bi.id = '1234';
but got a result like this:
{
"id": "1234",
"street_name": "a street",
"features1": [
2,
2,
2,
1,
1,
1
],
"features2": [
3,
2,
1,
3,
2,
1
]
}
Upvotes: 2
Views: 234
Reputation: 2959
SELECT A.*, B.*, C_GROUPED.C_STUFF, D_GROUPED.D_STUFF
FROM A
INNER JOIN B ON B.A_ID = A.ID
LEFT JOIN ( SELECT A_ID, JSON_AGG(STUFF) AS C_STUFF FROM C GROUP BY A_ID ) AS C_GROUPED ON C_GROUPED.A_ID = A.ID
LEFT JOIN ( SELECT A_ID, JSON_AGG(OTHER_STUFF) AS D_STUFF FROM D GROUP BY A_ID ) AS D_GROUPED ON D_GROUPED.A_ID = A.ID
WHERE A.ID = 123;
should return the same result as
SELECT
A.*,
B.*,
( SELECT JSON_AGG(STUFF) FROM C WHERE C.A_ID = A.ID ) AS C_STUFF,
( SELECT JSON_AGG(OTHER_STUFF) FROM D WHERE D.A_ID = A.ID ) AS D_STUFF
FROM A
INNER JOIN B ON B.A_ID = A.ID
WHERE A.ID = 123
In fact, I would expect the second query be faster.
Ps - Since LEFT JOIN and LEFT OUTER JOIN are the same, I would suggest writing them in the same way in your query.
Upvotes: 1