1

I am trying to build a nested Json structure from a single table.

I am trying to get the final result to look like:

[
    {
        "contract_number":"GS00F0XXX",
        'category': [
            {
                'cat_id': "874 1",
                'socio': {
                    "eighta":false,
                    "sdvosb":false,
                    "edwosb":false
                }   
            },
            {
                "cat_id":"874 6",
                'socio': {
                    "eighta":false,
                    "sdvosb":false,
                    "edwosb":false,
                }
            }
        ]
    },
    {
        'contract_number': "GS00Q14OAXXX",
        'category': [
            {
                'cat_id': 'OASIS POOL1',
                'socio': ...
            }
        ]
    }  
]

The underlying table looks something like:

contract_type   contract_number duns_number eighta  sdvosb  edwosb  category
MOBIS           GS00F0XXX       5555555     FALSE   FALSE   FALSE   874 1
MOBIS           GS00F0XXX       5555555     FALSE   FALSE   FALSE   874 6
MOBIS           GS00F0XXX       5555555     FALSE   FALSE   FALSE   874 7
OASIS           GS00Q14OAXXX    5555555     FALSE   FALSE   FALSE   OASIS POOL1
OASIS           GS00Q14OAXXX    5555555     FALSE   FALSE   FALSE   OASIS POOL2

I've tried this query, but it puts everything on two rows, and every time I try to nest a json_agg call I get an error about nestng aggregation functions.

select 
    json_build_object(
        'contract_number', contract_number,
        'info', json_agg(
            json_build_object(
                    'category_id', category,
                    'eighta',eighta,
                    'sdvosb',sdvosb,
                    'edwosb',edwosb
                )
        )
    )
from contract_vehicle
group by duns_number, contract_number

This results in SQL Error [42803]: ERROR: aggregate function calls cannot be nested

select 
    json_build_object(
        'contract_number', contract_number,
        'info', json_agg(
            json_build_object(
                    'category_id', category,
                    'socio', jsonb_agg(
                        json_build_object(
                            'eighta',eighta,
                            'sdvosb',sdvosb,
                            'edwosb',edwosb
                        )
                    )
                )
        )
    )
from contract_vehicle
group by duns_number, contract_number 
4
  • What version of Postgres are you using? Commented Oct 31, 2018 at 13:49
  • I am using Postgres 9.6. Commented Oct 31, 2018 at 14:58
  • @Sorix json support were added in postgres from version 9.3 Commented Oct 31, 2018 at 15:01
  • @SABER - FICTIONAL CHARACTER json_build_object() is supported on 9.4 or newer Commented Oct 31, 2018 at 15:23

1 Answer 1

1

I am not sure this will work but give it a try :)

with cte as (
    select  json_agg(
                        json_build_object(
                            'eighta',eighta,
                            'sdvosb',sdvosb,
                            'edwosb',edwosb
                        )
                    ) a1,duns_number dn, contract_number cn
    from contract_vehicle
    group by duns_number, contract_number)
select json_build_object(
        'contract_number'::text, contract_number::text,
        'info'::text, json_agg(
            json_build_object(
                    'category_id'::text, category::text,
                    'socio'::text, a1
                )
        )
    )
from contract_vehicle inner join cte on (duns_number=dn and contract_number = cn)
group by duns_number, contract_number;
Sign up to request clarification or add additional context in comments.

2 Comments

I it still giving me the two contract# on two rows. I think I have to build an additional cte that nests inside the one you wrote. I think with your example I can figure it out.
I'm glad it helped. FYI- You can use string_agg() over() function to merge the two rows accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.