sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでJSONB値をマージしますか?

    jsonb_each()を使用してネストされていない要素をマージする必要があります 両方の値について。自明でないクエリでこれを行うのは不快かもしれないので、私はこのようなカスタム関数を好むでしょう:

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

    使用:

    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)
    

    再帰を使用して関数をわずかに変更し、任意のレベルのネストでソリューションを機能させることができます。

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

    例:

    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)
    

    最後に、OPによって提案された変更を含む関数のバリアント(以下のコメントを参照):

    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. オンラインアップグレードの進捗状況

    2. 東京のMariaDB

    3. 関数からクエリを返しますか?

    4. GROUPBY句のないMySQL集計関数