sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo puedo fusionar registros dentro de dos matrices JSON?

Asumiendo tipo de datos jsonb y que desea fusionar registros de cada matriz JSON que comparten el mismo valor de 'id'.

Postgres 9.5

lo simplifica con el nuevo 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);

El FULL [OUTER] JOIN se asegura de no perder registros sin coincidencia en la otra matriz.

El tipo jsonb tiene la propiedad conveniente de mantener solo el valor más reciente para cada clave en el registro. Por lo tanto, la clave 'id' duplicada en el resultado se fusiona automáticamente.

El manual de Postgres 9.5 también aconseja:

Postgres 9.4

Es un poco menos conveniente. Mi idea sería extraer elementos de la matriz, luego extraer todos los pares clave/valor, UNION ambos resultados, agregados en un solo nuevo jsonb valores por valor de identificación y finalmente se agregan en una sola 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;

El elenco a jsonb elimina llaves duplicadas. Alternativamente, podría usar UNION para plegar duplicados (por ejemplo, si desea json como resultado). Prueba cuál es más rápido para tu caso.

Relacionado: