0

I have a table named loans with a lot of fields such as (id, name, description, etc.) And inside that table, I have a column which type is JSON(TermsMessage)(ARRAY OF JSON), and when I make a select query it returns me an error

my query

`

  select 
    z.loan_id, 
    z.loan_name, 
    z.max_amount, 
    z.min_amount,
        z.min_age,
        z.max_age,
        z.min_loan_term,
        z.max_loan_term,
        z.TermsMessage,
    to_json(array_agg(distinct z.jsjs)) as aims,
    to_json(array_agg(distinct z.jsjs1)) as cities,
    from(
        select 
        c.loan_id, 
        c.loan_name, 
        c.max_amount,
        c.min_amount,
        c.min_age,
        c.max_age,
        c.min_loan_term,
        c.max_loan_term,
        c.TermsMessage,
        ( select x from (select c.aim_id, c.aim_name) x) as jsjs,
        ( select x from (select c.city_id, c.city_name) x) as jsjs1
        from 
        ( select 
        l.id as loan_id, 
        l.name as loan_name, 
        l.max_amount, 
        l.min_amount,
        l.min_age,
        l.max_age,
        l.min_loan_term,
        l.max_loan_term,
        l.TermsMessage,
        --
        a.id as aim_id, 
        a.name as aim_name,
        --
        c.id as city_id,
        c.name as city_name
        --
        from loans as l
        left join loan_aims as la on la._loan = l.id
        left join aims as a on a.id = la._aim
        ------------
        left join loan_cities as lc on lc._loan=l.id
        left join cities as c on c.id = lc._city
        ------------

        ) c     
    ) z
    group by z.loan_id,
        z.loan_name, 
        z.max_amount,
        z.min_amount,
        z.min_age,
        z.max_age,
        z.min_loan_term,
        z.max_loan_term;

`

termsMessage must appear in the GROUP BY clause or be used in an aggregate function

and when I add json column into GROUP BY it return an another error

 group by z.loan_id,
            z.loan_name, 
            z.max_amount,
            z.min_amount,
            z.min_age,
            z.max_age,
            z.min_loan_term,
            z.max_loan_term,
            z.TermsMessage;

could not identify an equality operator for type json

1 Answer 1

1

PostgreSQL doesn't have a built-in equality operator for the datatypes JSON or arrays of JSON. When grouping by a JSON field, the db needs to know which are the same values and can be grouped together. You can work around this by turning the JSON (or JSON arrays) into either text arrays or JSONb arrays using something like ::jsonb[] or ::text[]. I'd probably do in the innermost part of the query so that it flows through later naturally:

  select 
    z.loan_id, 
    z.loan_name, 
    z.max_amount, 
    z.min_amount,
        z.min_age,
        z.max_age,
        z.min_loan_term,
        z.max_loan_term,
        z.TermsMessage,
    to_json(array_agg(distinct z.jsjs)) as aims,
    to_json(array_agg(distinct z.jsjs1)) as cities,
    from(
        select 
        c.loan_id, 
        c.loan_name, 
        c.max_amount,
        c.min_amount,
        c.min_age,
        c.max_age,
        c.min_loan_term,
        c.max_loan_term,
        c.TermsMessage,
        ( select x from (select c.aim_id, c.aim_name) x) as jsjs,
        ( select x from (select c.city_id, c.city_name) x) as jsjs1
        from 
        ( select 
        l.id as loan_id, 
        l.name as loan_name, 
        l.max_amount, 
        l.min_amount,
        l.min_age,
        l.max_age,
        l.min_loan_term,
        l.max_loan_term,
        l.TermsMessage::jsonb[] as TermsMessage ,
        --
        a.id as aim_id, 
        a.name as aim_name,
        --
        c.id as city_id,
        c.name as city_name
        --
        from loans as l
        left join loan_aims as la on la._loan = l.id
        left join aims as a on a.id = la._aim
        ------------
        left join loan_cities as lc on lc._loan=l.id
        left join cities as c on c.id = lc._city
        ------------

        ) c     
    ) z
    group by z.loan_id,
        z.loan_name, 
        z.max_amount,
        z.min_amount,
        z.min_age,
        z.max_age,
        z.min_loan_term,
        z.max_loan_term,
        z.TermsMessage;
Sign up to request clarification or add additional context in comments.

1 Comment

Sure. Fun background (as it originally seemed crazy to me that there was no JSON equality operator built in): PostgreSQL stores JSON to maintain the order of keys added to it, while JSONB does not. For your use case it probably does not matter, but you can actually get different results on the equality test depending on if you convert to JSONB or to text (since text will also maintain the difference in key order). With that, it makes sense that you'd need to convert one way or the other to compare equality.

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.