sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur kan jag slå samman poster i två JSON-arrayer?

Förutsatt datatyp jsonb och att du vill slå samman poster för varje JSON-array som delar samma "id"-värde.

Postgres 9.5

gör det enklare med den nya sammansättningen operator || för jsonb värden :

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

FULL [OUTER] JOIN ser till att du inte förlorar rekord utan matchning i den andra arrayen.

Typen jsonb har den bekväma egenskapen att endast behålla det senaste värdet för varje nyckel i posten. Därför slås den dubbla 'id'-nyckeln i resultatet samman automatiskt.

Postgres 9.5-manualen ger också råd om:

Postgres 9.4

Är lite mindre bekvämt. Min idé skulle vara att extrahera arrayelement och sedan extrahera alla nyckel/värdepar, UNION båda resultaten samlas till en enda ny jsonb värden per id-värde och slutligen aggregeras till en enda 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;

Casten till jsonb tar bort dubbletter av nycklar. Alternativt kan du använda UNION att vika dubbletter (till exempel om du vill ha json som resultat). Testa vilket som är snabbare för ditt fall.

Relaterat:



  1. MySQL kumulativ produktgrupp efter

  2. Varning:PDO::__construct():[2002] Ingen sådan fil eller katalog (försöker ansluta via unix:///tmp/mysql.sock) i

  3. Förbeställning av en GROUP BY-sats

  4. ASCII()-funktion i Oracle