PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment puis-je fusionner des enregistrements dans deux tableaux JSON ?

En supposant type de données jsonb et que vous souhaitez fusionner les enregistrements de chaque tableau JSON qui partagent la même valeur 'id'.

Postgres 9.5

simplifie les choses avec le nouveau concaténer opérateur || pour jsonb valeurs :

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);

La FULL [OUTER] JOIN s'assure que vous ne perdez pas d'enregistrements sans correspondance dans l'autre tableau.

Le type jsonb a la propriété pratique de ne conserver que la dernière valeur de chaque clé dans l'enregistrement. Par conséquent, la clé 'id' en double dans le résultat est fusionnée automatiquement.

Le manuel Postgres 9.5 conseille également :

Postgres 9.4

Est un peu moins pratique. Mon idée serait d'extraire les éléments du tableau, puis d'extraire toutes les paires clé/valeur, UNION les deux résultats, agrégés en un seul nouveau jsonb valeurs par valeur d'identifiant et enfin agrégées dans un seul tableau.

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;

Le cast en jsonb supprime les clés en double. Vous pouvez également utiliser UNION pour plier les doublons (par exemple si vous voulez json à la suite). Testez ce qui est le plus rapide pour votre cas.

Connexe :