Reputation: 6981
If I have a query like this:
SELECT
u.client_code,
max(d.created_at) as last_document_created_at,
u.brand_id,
t.name as template_name,
count(d)
FROM users u
INNER JOIN documents d ON u.id = d.user_id
INNER JOIN templates t ON t.id = d.template_id
GROUP BY 1, 3, 4
Which returns information like this:
client_code last_document_created_at brand_id template_name count
---------------------------------------------------------------------
client1 2017-12-06 10:03:47 +1100 39 newsletter_r 1
client1 2017-12-05 15:23:24 +1100 39 Other media 5
client2 2017-12-21 17:07:11 +1100 39 newsletter_r 4
client3 2018-01-11 12:10:43 +1100 39 newsletter_r 2
client3 2017-12-06 11:45:21 +1100 39 Other media 1
What are my options to concatenate the template_name
and count
fields so that each user (represented in u.client_code
) is on one line? I know I can call string_agg
the column like so:
...
string_agg(distinct t.name, ', ') as template_name,
...
But that of course ruins the respective counts:
newsletter_r, Other media 6
Update
I could do this:
string_agg(concat_ws(': ', t.name::text, count(d)::text), ', ') as template_count
But that gives me an error:
aggregate function calls cannot be nested LINE 5: string_agg(concat_ws(': ', t.name::text, count(d)::text)... ^ : SELECT u.client_code,
Upvotes: 0
Views: 2373
Reputation: 1269443
I think you want something like this:
SELECT u.client_code,
max(d.created_at) as last_document_created_at,
u.brand_id,
string_agg(t.name, ',') as template_name,
count(distinct d.id)
FROM users u INNER JOIN
documents d
ON u.id = d.user_id INNER JOIN
templates t
ON t.id = d.template_id
GROUP BY 1, 3;
Upvotes: 0
Reputation: 3823
Not sure how you want to format your concatenated field, but have you tried putting your original query into a sub-query and applying a string_agg
to it? Something like this:
SELECT client_code, STRING_AGG(template_name || template_count, ',')
FROM (
SELECT
u.client_code,
MAX(d.created_at) AS last_document_created_at,
u.brand_id,
t.name AS template_name,
COUNT(d) AS template_count
FROM users u
INNER JOIN documents d ON u.id = d.user_id
INNER JOIN templates t ON t.id = d.template_id
GROUP BY 1, 3, 4
) src
GROUP BY client_code
I haven't tested it, so you may have some syntax errors. Let me know if that works.
Upvotes: 1