PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come posso unire i record all'interno di due array JSON?

Supponendo tipo di dati jsonb e che desideri unire i record di ogni array JSON che condividono lo stesso valore "id".

Postgres 9,5

lo rende più semplice con il nuovo concatena operatore || per jsonb valori :

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

Il FULL [OUTER] JOIN assicura di non perdere record senza corrispondenza nell'altro array.

Il tipo jsonb ha la proprietà conveniente per mantenere solo il valore più recente per ogni chiave nel record. Pertanto, la chiave "id" duplicata nel risultato viene unita automaticamente.

Il manuale di Postgres 9.5 consiglia inoltre:

Postgres 9.4

È un po' meno conveniente. La mia idea sarebbe quella di estrarre gli elementi dell'array, quindi estrarre tutte le coppie chiave/valore, UNION entrambi i risultati, aggregati in un unico nuovo jsonb valori per valore id e infine aggregati in un unico 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;

Il cast a jsonb rimuove le chiavi duplicate. In alternativa puoi usare UNION per piegare i duplicati (ad esempio se vuoi json come risultato). Verifica quale è più veloce per il tuo caso.

Correlati: