postgresql

Merging Concatenating JSON(B) columns in query


Using Postgres 9.4, I am looking for a way to merge two (or more) json or jsonb columns in a query. Consider the following table as an example:

  id | json1        | json2
----------------------------------------
  1   | {'a':'b'}   | {'c':'d'}
  2   | {'a1':'b2'} | {'f':{'g' : 'h'}}

Is it possible to have the query return the following:

  id | json
----------------------------------------
  1   | {'a':'b', 'c':'d'}
  2   | {'a1':'b2', 'f':{'g' : 'h'}}

Unfortunately, I can't define a function as described here. Is this possible with a "traditional" query?


Solution

  • Here is the complete list of build-in functions that can be used to create json objects in PostgreSQL. http://www.postgresql.org/docs/9.4/static/functions-json.html

    Well... ok, wo we can't use any classic functions.

    Let's take a look at some aggregate functions and hope for the best... http://www.postgresql.org/docs/9.4/static/functions-aggregate.html

    json_object_agg Is the only aggregate function that build objects, that's our only chance to tackle this problem. The trick here is to find the correct way to feed the json_object_agg function.

    Here is my test table and data

    CREATE TABLE test (
      id    SERIAL PRIMARY KEY,
      json1 JSONB,
      json2 JSONB
    );
    
    INSERT INTO test (json1, json2) VALUES
      ('{"a":"b", "c":"d"}', '{"e":"f"}'),
      ('{"a1":"b2"}', '{"f":{"g" : "h"}}');
    

    And after some trials and errors with json_object here is a query you can use to merge json1 and json2 in PostgreSQL 9.4

    WITH all_json_key_value AS (
      SELECT id, t1.key, t1.value FROM test, jsonb_each(json1) as t1
      UNION
      SELECT id, t1.key, t1.value FROM test, jsonb_each(json2) as t1
    )
    SELECT id, json_object_agg(key, value) 
    FROM all_json_key_value 
    GROUP BY id
    

    For PostgreSQL 9.5+, look at Zubin's answer.