PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como posso mesclar registros dentro de duas matrizes JSON?


Supondo tipo de dados jsonb e que você deseja mesclar registros de cada matriz JSON que compartilham o mesmo valor 'id'.

Postgres 9.5


torna tudo mais simples com o novo concatenar operador || para jsonb valores :
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);

O FULL [OUTER] JOIN garante que você não perca registros sem correspondência na outra matriz.

O tipo jsonb tem a propriedade conveniente de manter apenas o valor mais recente para cada chave no registro. Portanto, a chave 'id' duplicada no resultado é mesclada automaticamente.

O manual do Postgres 9.5 também aconselha:

Postgres 9.4


É um pouco menos conveniente. Minha ideia seria extrair elementos de matriz e extrair todos os pares de chave/valor, UNION ambos os resultados, agregados em um único novo jsonb valores por valor de id e, finalmente, agregar em uma única matriz.
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;

A conversão para jsonb remove chaves duplicadas. Alternativamente, você pode usar UNION dobrar duplicatas (por exemplo, se você quiser json como resultado). Teste qual é mais rápido para o seu caso.

Relacionado: