SELECT users.user_id, GROUP_CONCAT(tags.tag_id SEPARATOR ',') AS tags
FROM users
LEFT JOIN user_tags ON users.user_id = user_tags.user_id
LEFT JOIN tags ON tags.tag_id = user_tags.tag_id
WHERE tags.tag_id IN (1)
GROUP BY users.user_id
Thanks, but that means to select users who are assigned with tag_id = 1 OR tag_id = 2, which, as in my test, also selects a user who is assigned with tag_id = 2 but not with tag_id = 1.
I want to select users assigned with tag_id = 1, and I want to display all tags for each user. (I can do this using one extra query for each user with something like get_user_tags(user_id), but I am trying to do it with a single query if possible.)
You can’t have it both ways with the query you’re using. The group_concat only works with the records that are filtered through the where clause. You’ll need to use a sub-query
SELECT users.user_id
, tagList
FROM users
LEFT JOIN (SELECT user_tags.user_id
, GROUP_CONCAT(tags.tag_id SEPARATOR ',') AS tagList
FROM user_tags ON users.user_id = user_tags.user_id
INNER JOIN tags ON tags.tag_id = user_tags.tag_id
GROUP BY user_tags.user_id) SQ ON SQ.user_id = users.user_id
INNER JOIN user_tags ON users.user_id = user_tags.user_id
WHERE user_tags.tag_id = 1
A couple notes:
I changed all the LEFT JOINS to INNER JOINS because you’re using a WHERE clause on the joined table and are looking for a specific value, which requires a match, hence an INNER JOIN.
I removed the second join on the main clause since you’re just looking for the tag_id. If you’re not pulling an actual value from the tags table, you can remove the second join from the second query. I left it there since I thought you might be pulling a different value from the tags table (like tag name or description) which would need the second join. But if you’re just filtering by tag_id, the second join isn’t needed.
I changed the IN to = since you’re only looking for one value. Depending on the indexing on the field, a table scan can be avoided if using the equal operator, which improves performance.