PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann ich Datensätze in zwei JSON-Arrays zusammenführen?

Vorausgesetzt Datentyp jsonb und dass Sie Datensätze jedes JSON-Arrays zusammenführen möchten, die denselben 'id'-Wert haben.

Postgres 9.5

macht es einfacher mit dem neuen concatenate Operator || für jsonb Werte :

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

Der FULL [OUTER] JOIN stellt sicher, dass Sie keine Datensätze ohne Übereinstimmung im anderen Array verlieren.

Der Typ jsonb hat die bequeme Eigenschaft, nur den neuesten Wert für jeden Schlüssel im Datensatz zu behalten. Daher wird der doppelte 'id'-Schlüssel im Ergebnis automatisch zusammengeführt.

Das Postgres 9.5-Handbuch empfiehlt auch:

Postgres 9.4

Ist etwas weniger bequem. Meine Idee wäre, Array-Elemente zu extrahieren und dann alle Schlüssel/Wert-Paare zu extrahieren, UNION beide Ergebnisse werden zu einem einzigen neuen jsonb aggregiert Werte pro ID-Wert und schließlich zu einem einzigen Array aggregieren.

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;

Die Umwandlung in jsonb entfernt doppelte Schlüssel. Alternativ können Sie UNION verwenden um Duplikate zu falten (zum Beispiel, wenn Sie json als Ergebnis). Testen Sie, was für Ihren Fall schneller ist.

Verwandte: