Aangenomen gegevenstype jsonb
en dat u records van elke JSON-array wilt samenvoegen die dezelfde 'id'-waarde delen.
Postgres 9,5
maakt het eenvoudiger met de nieuwe concatenate operator ||
voor jsonb
waarden
:
SELECT json_agg(elem1 || elem2) AS result
FROM (
SELECT elem1->>'id' AS id, elem1
FROM (
SELECT '[
{"id":1, "percent":12.50},
{"id":2, "percent":75.00},
{"id":3, "percent":12.50}
]'::jsonb AS js
) t, jsonb_array_elements(t.js) elem1
) t1
FULL JOIN (
SELECT elem2->>'id' AS id, elem2
FROM (
SELECT '[
{"id": 1, "a": "text1a", "b": "text1b", "percent":12.50},
{"id": 2, "a": "text2a", "b": "text2b", "percent":75.00},
{"id": 3, "a": "text3a", "b": "text3b", "percent":12.50}]'::jsonb AS js
) t, jsonb_array_elements(t.js) elem2
) t2 USING (id);
De FULL [OUTER] JOIN
zorgt ervoor dat u geen records verliest zonder match in de andere array.
Het type jsonb
heeft de handige eigenschap om alleen de laatste waarde voor elke sleutel in de record te behouden. Daarom wordt de dubbele 'id'-sleutel in het resultaat automatisch samengevoegd.
De Postgres 9.5-handleiding adviseert ook:
Postgres 9.4
Is wat minder handig. Mijn idee zou zijn om array-elementen te extraheren en vervolgens alle sleutel/waarde-paren te extraheren, UNION
beide resultaten worden samengevoegd tot één nieuwe jsonb
waarden per id-waarde en uiteindelijk samenvoegen tot een enkele array.
SELECT json_agg(j) -- ::jsonb
FROM (
SELECT json_object_agg(key, value)::jsonb AS j
FROM (
SELECT elem->>'id' AS id, x.*
FROM (
SELECT '[
{"id":1, "percent":12.50},
{"id":2, "percent":75.00},
{"id":3, "percent":12.50}]'::jsonb AS js
) t, jsonb_array_elements(t.js) elem, jsonb_each(elem) x
UNION ALL -- or UNION, see below
SELECT elem->>'id' AS id, x.*
FROM (
SELECT '[
{"id": 1, "a": "text1a", "b": "text1b", "percent":12.50},
{"id": 2, "a": "text2a", "b": "text2b", "percent":75.00},
{"id": 3, "a": "text3a", "b": "text3b", "percent":12.50}]'::jsonb AS js
) t, jsonb_array_elements(t.js) elem, jsonb_each(elem) x
) t
GROUP BY id
) t;
De cast naar jsonb
verwijdert dubbele sleutels. Als alternatief kunt u UNION
. gebruiken om duplicaten te vouwen (bijvoorbeeld als u json
. wilt als resultaat). Test wat sneller is voor jouw geval.
Gerelateerd: