Merge nested ARRAY of JSONB fields with a JOIN-like statement in PostgreSQL?

笑着哭i 提交于 2019-12-14 02:35:18

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!