1

I currently have this LEFT JOIN which is part of a bigger select

LEFT JOIN (
  SELECT
    tags_components.component_id,
    array_to_json(array_agg(tags.*)) as tags
    FROM tags_components
    LEFT JOIN tags ON tags.id = tags_components.tag_id AND tags_components.component_name = 'contact'
    GROUP BY tags_components.component_id
) AS tags ON tags.component_id = contact.id

Which works as expected if component has all tags assigned. However tags array is always of size COUNT(tags.*) so for component without any tags is filled with null. Is there a way how filter those nulls out? I tried different things like using json_strip_nulls or having FILTER on the array but I didn't achieve the right result (JSON array containing only non-nulls)

2 Answers 2

4

If I understood everything correctly then the issue you face is in the line:

...
array_to_json(array_agg(tags.*)) as tags
...

Maybe you used FILTER in a wrong way, but this does work to eliminta NULL results like:

SELECT  array_to_json(
            -- FILTER is applied to this specific 'array_agg'
            array_agg( t.* ) FILTER ( WHERE t.tag IS NOT NULL )
        )
FROM    ( VALUES
            ( 'a1' ),
            ( 'b1' ),
            ( null ),
            ( 'c1' ),
            ( null ),
            ( 'd1' )
        ) t( tag );

-- Resolves to:
                     array_to_json
-------------------------------------------------------
 [{"tag":"a1"},{"tag":"b1"},{"tag":"c1"},{"tag":"d1"}]
(1 row)

Alternatively you can use jsonb_agg (read more at Postgres Aggregate Functions) instead of array_to_json + array_agg to provide same result like:

SELECT  jsonb_agg( t.* ) FILTER ( WHERE t.tag IS NOT NULL )
FROM    ( VALUES
            ( 'a1' ),
            ( 'b1' ),
            ( null ),
            ( 'c1' ),
            ( null ),
            ( 'd1' )
        ) t( tag );
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, the filter really worked. I would bet I wrote exactly the same code but apparently not :)
2

array_remove function is going to be your best bet now: array_to_json(array_remove(array_agg(tags.*), null)) as tags

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.