sql >> Database >  >> RDS >> PostgreSQL

Hoe kan ik records samenvoegen in twee JSON-arrays?

Aangenomen gegevenstype jsonb en dat u records van elke JSON-array wilt samenvoegen die dezelfde 'id'-waarde delen.

Postgres 9,5

maakt het eenvoudiger met de nieuwe concatenate operator || voor jsonb waarden :

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

De FULL [OUTER] JOIN zorgt ervoor dat u geen records verliest zonder match in de andere array.

Het type jsonb heeft de handige eigenschap om alleen de laatste waarde voor elke sleutel in de record te behouden. Daarom wordt de dubbele 'id'-sleutel in het resultaat automatisch samengevoegd.

De Postgres 9.5-handleiding adviseert ook:

Postgres 9.4

Is wat minder handig. Mijn idee zou zijn om array-elementen te extraheren en vervolgens alle sleutel/waarde-paren te extraheren, UNION beide resultaten worden samengevoegd tot één nieuwe jsonb waarden per id-waarde en uiteindelijk samenvoegen tot een enkele 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;

De cast naar jsonb verwijdert dubbele sleutels. Als alternatief kunt u UNION . gebruiken om duplicaten te vouwen (bijvoorbeeld als u json . wilt als resultaat). Test wat sneller is voor jouw geval.

Gerelateerd:



  1. Hoe kan ik een back-up maken van een externe SQL Server-database naar een lokale schijf?

  2. Kan geen waarden (NULL) gebruiken in python mysql.connector in voorbereide INSERT-instructie

  3. Mysql - zoekvelden die eindigen als zoekterm

  4. SQL Server TempDB-bestandslocatie wijzigen