21

I have a json query that gives me json of a joined table of person and pets:

SELECT json_object(
  'personId', p.id,
  'pets', json_arrayagg(json_object(
    'petId', pt.id,
    'petName', pt.name
  ))
  )
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;

my issue is that person can have 0 or more pets, and when a person have 0 pets I get list with 1 empty pet, and what I would like to get in that case is empty list.

this is what I get:

{
  "personId": 1,
  "pets": [
    {
      "petId": null,
      "petName": ""
    }
  ]
}

and I need:

{
  "personId": 1,
  "pets": []
}

is that possible?

1

3 Answers 3

32

The problem is that LEFT JOIN still returns columns from the table you're joining with, it just sets their values to NULL.

You can use IF to test COUNT(pt.id), as this won't count null values.

SELECT json_object(
  'personId', p.id,
  'pets', IF(COUNT(pt.id) = 0, JSON_ARRAY(),
             json_arrayagg(json_object(
                'petId', pt.id,
                'petName', pt.name
                )
            ))
  )
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;
Sign up to request clarification or add additional context in comments.

3 Comments

Working Perfect.. THanks
Thank you so much, IF( COUNT(...), ... , ... ) is a really nice trick, it had to be an aggregated function but I couldn't figure out which and how to use! )
This also worked for me
7

Another possibility is to put the aggregation in a correlated subquery and use coalesce() to replace it with an empty array if no rows exist.

SELECT json_object('personID', p.id,
                   'pets', coalesce((SELECT json_arrayagg(json_object('petId', t.id,
                                                                      'petName', t.name))
                                            FROM pets t
                                            WHERE t.person_id = p.id),
                                    json_array()))
       FROM person p;

Comments

1

Adding another option:

select IFNULL( /*expression of select ...JSON_ARRAYAGG(
                                    JSON_OBJECT(....*/,JSON_ARRAY()) jarrayaggAlias

Cleaner below:

IFNULL( expression, ,JSON_ARRAY()) jarrayaggAlias

Result:

/* { jarrayaggAlias: []  }*/

If you swap alt_value for IFNULL to select [], then all your results will be stringyfied.

Comments

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.