sql >> Databasteknik >  >> RDS >> PostgreSQL

Sammanfoga JSONB-värden i PostgreSQL?

Du bör slå samman okapslade element med jsonb_each() för båda värdena. Att göra detta i en icke-trivial fråga kan vara obekvämt, så jag skulle föredra en anpassad funktion som den här:

create or replace function jsonb_my_merge(a jsonb, b jsonb)
returns jsonb language sql as $$
    select 
        jsonb_object_agg(
            coalesce(ka, kb), 
            case 
                when va isnull then vb 
                when vb isnull then va 
                else va || vb 
            end
        )
    from jsonb_each(a) e1(ka, va)
    full join jsonb_each(b) e2(kb, vb) on ka = kb
$$;

Använd:

select jsonb_my_merge(
    '{"a":{"b":2}, "d": {"e": 10}, "x": 1}'::jsonb, 
    '{"a":{"c":3}, "d": {"f": 11}, "y": 2}'::jsonb
)

                          jsonb_my_merge                          
------------------------------------------------------------------
 {"a": {"b": 2, "c": 3}, "d": {"e": 10, "f": 11}, "x": 1, "y": 2}
(1 row)

Du kan ändra funktionen något med hjälp av rekursion för att få en lösning att fungera på alla nivåer av kapsling:

create or replace function jsonb_recursive_merge(a jsonb, b jsonb)
returns jsonb language sql as $$
    select 
        jsonb_object_agg(
            coalesce(ka, kb), 
            case 
                when va isnull then vb 
                when vb isnull then va 
                when jsonb_typeof(va) <> 'object' then va || vb
                else jsonb_recursive_merge(va, vb)
            end
        )
    from jsonb_each(a) e1(ka, va)
    full join jsonb_each(b) e2(kb, vb) on ka = kb
$$;

Exempel:

select jsonb_recursive_merge( 
    '{"a":{"b":{"c":3},"x":5}}'::jsonb, 
    '{"a":{"b":{"d":4},"y":6}}'::jsonb);

             jsonb_recursive_merge              
------------------------------------------------
 {"a": {"b": {"c": 3, "d": 4}, "x": 5, "y": 6}}
(1 row)

select jsonb_recursive_merge(
    '{"a":{"b":{"c":{"d":{"e":1}}}}}'::jsonb, 
    '{"a":{"b":{"c":{"d":{"f":2}}}}}'::jsonb)

            jsonb_recursive_merge             
----------------------------------------------
 {"a": {"b": {"c": {"d": {"e": 1, "f": 2}}}}}
(1 row)

Slutligen, varianten av funktionen med ändringar föreslagna av OP (se kommentarer nedan):

create or replace function jsonb_recursive_merge(a jsonb, b jsonb) 
returns jsonb language sql as $$ 
select 
    jsonb_object_agg(
        coalesce(ka, kb), 
        case 
            when va isnull then vb 
            when vb isnull then va 
            when jsonb_typeof(va) <> 'object' or jsonb_typeof(vb) <> 'object' then vb 
            else jsonb_recursive_merge(va, vb) end 
        ) 
    from jsonb_each(a) e1(ka, va) 
    full join jsonb_each(b) e2(kb, vb) on ka = kb 
$$;


  1. Formatera månaden i romerska siffror i PostgreSQL

  2. Undvik sortering med Merge Join-konkatenering

  3. Skapa en MySQL-databas

  4. Topp 10 intressanta fakta och tips om MySQL