Приемаме тип данни jsonb
и че искате да обедините записи на всеки JSON масив, които споделят една и съща стойност на 'id'.
Postgres 9.5
го прави по-прост с новия конкатенация оператор ||
за jsonb
стойности
:
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);
FULL [OUTER] JOIN
гарантира, че няма да загубите записи без съвпадение в другия масив.
Типът jsonb
има удобното свойство да съхранява само най-новата стойност за всеки ключ в записа. Следователно дублираният ключ 'id' в резултата се обединява автоматично.
Ръководството за Postgres 9.5 също съветва:
Postgres 9.4
Малко по-малко удобно е. Идеята ми е да извлека елементи от масива, след което да извлека всички двойки ключ/стойност, UNION
и двата резултата се обединяват в един нов jsonb
стойности на id стойност и накрая се събират в един масив.
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;
Прехвърлянето към jsonb
премахва дублиращи се ключове. Като алтернатива можете да използвате UNION
за сгъване на дубликати (например, ако искате json
като резултат). Тествайте кое е по-бързо за вашия случай.
Свързани: