1

I've come up with a query to create concatenated string based on a conditional statement using STRING_AGG in Postgress. That works just fine but I want to sort the result as well without duplicating the CASE.

This is what I have now:

SELECT
STRING_AGG(distinct name, ', ' ORDER BY name),
STRING_AGG(
  DISTINCT
  CASE WHEN something = true THEN 'type1'
       WHEN something_else = true THEN 'type2'
       ELSE 'type3'
  END, ', '
ORDER BY
  CASE WHEN something = true THEN 'type1'
       WHEN something_else = true THEN 'type2'
       ELSE 'type3'
  END

)
from organisations

..but I want to do something like this to not have the duplicated code and remove rows and complexity from my query but I can't figure out how to make it work, this is fake code that doesn't work obviously, but you get the idea:

SELECT
STRING_AGG(distinct name, ', ' ORDER BY name) names,
STRING_AGG(
  DISTINCT (
    CASE WHEN something = true THEN 'type1'
         WHEN something_else = true THEN 'type2'
         ELSE 'type3'
    END
  ) as types, ', ' ORDER BY types) types
from organisations

2 Answers 2

2

You don't require string_agg(). You could instead do:

SELECT STRING_AGG(distinct name, ', ' ORDER BY name) names,
       CONCAT_WS(',',
                 (CASE WHEN SUM( (something = true)::int ) > 0 THEN 'type1'),
                 (CASE WHEN SUM( (not (something = true) )::int ) > 0 THEN 'type2')
                ) as types
FROM organisations o;

You may have oversimplified the query, but for what you provided, you don't need string_agg(distinct) for the second portion.

Sign up to request clarification or add additional context in comments.

1 Comment

That is great, I could make your suggestion work for me, I would not have figured that one out myself. Thank you!
1

One option might be to compute the CASE expression first in a separate CTE, and then query that CTE to apply STRING_AGG:

WITH cte AS (
    SELECT
        name,
        CASE WHEN something = true THEN 'type1'
             WHEN something_else = true THEN 'type2'
             ELSE 'type2'
        END AS expr
    FROM organisations
)

SELECT
    STRING_AGG(distinct name, ', ' ORDER BY name),
    STRING_AGG(DISTINCT expr, ', ' ORDER BY expr)
FROM cte;

As a minor side note, since you have type2 as both the second and ELSE condition in the CASE expression, you might as well just use this:

CASE WHEN something = true THEN 'type1'
     ELSE 'type2'
END

1 Comment

Actually, the type2 in in the ELSE was a typo, thanks for pointing that out, I've not corrected it.

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.