问题
Given this tables:
BOOKS
id | data
----+-------------------------------------------------------
1 | { title: 'Book 1', price: 10.5, authors: [{ id: 1}, { id: 2 }]}
2 | { title: 'Book 2', price: 11.5, authors: [{ id: 2 } }
AUTHORS
id | data
-----+-------------------------------------------------------
1 | { name: 'Author 1', address: 'Address author 1' }
2 | { name: 'Author 2', address: 'Address author 2' }
Is it possible to obtain this result, by merging the authors key array elements, with a JOIN-like statement or using jsonb functions?
BOOKS QUERY RESULT
id | data
----+------------------------------------------------------------------------------------------------------
1 | { title: 'Book 1', price: 10.5, authors: [{ id: 1, name: 'Author 1', address: 'Address author 1' }, { id: 2, name: 'Author 2', address: 'Address author 2'}] }
2 | { title: 'Book 2', price: 11.5, authors: [{ id: 2, name: 'Author 2', address: 'Address author 2'}] }
Thanks
回答1:
The id arrays have to be unnested and results must be aggregated again what makes the query more complicated. I have changed a bit the arrays structure to more logical.
select b.data || jsonb_build_object('authors', jsonb_agg(a.data || jsonb_build_object('id', a.id)))
from books b
cross join jsonb_array_elements_text(b.data->'authors')
join authors a on a.id = value::int
group by b.id;
SqlFiddle
回答2:
There may be a more elegant way to do this but:
select
book_id,
jsonb_set(max(bdata :: text)::jsonb,
'{authors}',
jsonb_agg(nested.adata)) as author_data --aggregate authors into one jsonb arr
from (select
b.id as book_id,
b.data as bdata,
a.data as adata
from books b
join authors a
on b.data->'authors' @> concat('[{"id": ', a.id :: varchar, '}]') :: jsonb) as nested
group by book_id;
Relevant docs: see jsonb_set in https://www.postgresql.org/docs/9.5/static/functions-json.html and jsonb_agg at https://www.postgresql.org/docs/9.5/static/functions-aggregate.html
回答3:
select b.data || jsonb_build_object('authors', jsonb_agg(a.data ||
jsonb_build_object('id', a.id)))
from books b
left join (select id, jsonb_array_elements(data->'authors') from books) ba on
ba.id = b.id
left join authors a on a.id = ba.id
group by b.id;
来源:https://stackoverflow.com/questions/48993341/merge-nested-array-of-jsonb-fields-with-a-join-like-statement-in-postgresql