I have a setup like:
conversations(id)
notifications(id, conversation_id, user_id)
users(id)
If a conversation concerns someone, the user is linked to the conversation through one notification.
GOAL: I'm looking for conversations which concern exclusively users with given ids.
The obvious:
SELECT DISTINCT conversations.*
FROM "conversations"
INNER JOIN "notifications" ON "notifications"."conversation_id" = "conversations"."id"
WHERE notifications.user_id IN (1, 2)
doesn't work because it would also retrieve a conversation concerning:
- users with id 1, 2 and 3
- users with id 1 and 4
- users with id 2 and 4
and this is not desired.
This is assuming that each user can only be joined once to a conversation:
This is a special case of relational division. We have assembled a whole arsenal of techniques under this this related question:
How to filter SQL results in a has-many-through relation
The special requirement is to exclude additional matches. I use
NOT EXISTSfor this end. You could also useLEFT JOIN / IS NULLorNOT IN. More details here:Select rows which are not present in other table
There could be several notifications for the same user
To avoid duplicate conversations in the result you can use
DISTINCTorGROUP BYin addition to the above. Or you suppress duplicates to begin with (probably faster):