I have to join user_name from user table where as first_name and last_names from user_profile table. Until here everything is fine, but when I try to fetch respective roles assigned from user_role tables it gives multiple rows for single user as 1 user can have multiple roles.
While trying to apply string_agg
on role.names (so that multiple roles shown comma separated in single tuple), it gives each role in separate row.
Here is example query I am trying to run in postgresql:
SELECT users.user_name, user_profiles.first_name, user_profiles.last_name,
(
SELECT string_agg (roles.name, ',')
from roles
where roles.id in (
select user_roles.role_id where users.id = user_roles.user_id
)
) as name
FROM users
JOIN user_profiles ON users.id = user_profiles.user_id
JOIN user_roles ON user_roles.user_id = users.id
2
Answers
You must use
GROUP BY
clause in order to aggregate more than one record together within a group. That along with the unnecessary (I believe) nested SQL is leading you to wrong results.Instead consider the following:
Online demo
You forgot a
from
in your innermost subquery:without it, that subquery was just selecting one, current row’s
role_id
, instead independently fetching of all roles for the user as you could’ve expected it to. See this demo.Note that once this is fixed, you also need to get rid of the last join (commented out in my example) to avoid multiplying users for each of their roles – you’re already getting their roles in the innermost subquery anyways.
It would be easier to use a regular
group by
: