I have what seems to be a simple problem, but can not figure out the proper solution via SQL. I'm using postgresql specifically.
Take the following:
SELECT * FROM users INNER JOIN tags ON (tags.user_id = users.id) WHERE tags.name IN ('word1', 'word2')
This does not do what I need. I want to find users whose tags are ONLY included in the list. If the user has a tag that is not in the list, the user should not be included.
'user1' tags: word1, word2, word3
'user2' tags: word1
'user3' tags: word1, word2
Given: word1 and word2. I want to prepare a query that returns 'user2' and 'user3'. 'user1' is excluded because it has a tag that is not in the list.
Hopefully I made this clear. Thanks for your help!
Relying on COUNT(*) = 2 will require that there can be no duplicates of user_id and name in the tags table. If that's the case, I'd go that route. Otherwise, this should work:
SELECT u.*
FROM users AS u
WHERE u.id NOT IN (
SELECT DISTINCT user_id FROM tags WHERE name NOT IN ('word1', 'word2')
) AND EXISTS (SELECT user_id FROM tags WHERE user_id = u.id)
SELECT user_id
FROM users
WHERE id IN
(
SELECT user_id
FROM tags
)
AND id NOT IN
(
SELECT user_id
FROM tags
WHERE name NOT IN ('word1', 'word2')
)
or
SELECT u.*
FROM (
SELECT DISTINCT user_id
FROM tags
WHERE name IN ('word1', 'word2')
) t
JOIN users u
ON u.id = t.user_id
AND t.user_id NOT IN
(
SELECT user_id
FROM tags
WHERE name NOT IN ('word1', 'word2')
)
SELECT distinct users.id
FROM users
INNER JOIN tags ON (tags.user_id = users.id)
group by users.id
having count(*) = 2
and min(tags.name) = 'word1'
and max(tags.name) = 'word2'
To get all users that don't have a tag that is not in the list, use the query below. Could be that users are returned that have no tag or only one tag matching the words, but I understand that is the desired functionality.
SELECT
u.*
FROM
users u
LEFT JOIN tags t
ON t.user_id = u.userid AND
t.name NOT IN ('word1', 'word2')
WHERE
t.user_id IS NULL
SELECT u.*
FROM users u
INNER JOIN (
SELECT user_id FROM tags WHERE name IN ('word1', 'word2')
EXCEPT
SELECT user_id FROM tags WHERE name NOT IN ('word1', 'word2')
) s ON u.id = s.user_id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.