This is a case of relational division . We have put together an arsenal of methods on this related subject:
A particular difficulty is to exclude additional users. There are basically 4 methods.
I suggest LEFT JOIN / IS NULL :
SELECT cu1.conversation_id FROM conversation_user cu1 JOIN conversation_user cu2 USING (conversation_id) LEFT JOIN conversation_user cu3 ON cu3.conversation_id = cu1.conversation_id AND cu3.user_id NOT IN (3,32) WHERE cu1.user_id = 32 AND cu2.user_id = 3 AND cu3.conversation_id IS NULL;
Or NOT EXISTS :
SELECT cu1.conversation_id FROM conversation_user cu1 JOIN conversation_user cu2 USING (conversation_id) WHERE cu1.user_id = 32 AND cu2.user_id = 3 AND NOT EXISTS ( SELECT 1 FROM conversation_user cu3 WHERE cu3.conversation_id = cu1.conversation_id AND cu3.user_id NOT IN (3,32) );
Both queries are independent of the UNIQUE for (conversation_id, user_id) , which may or may not be in place. Meaning, the query even works if user_id 32 (or 3) is listed more than once for the same conversation. However, as a result, you get duplicate rows and must apply DISTINCT or GROUP BY .
The only condition you have formulated:
... a request that shows that there is a conversation between just user 32 and user 3?
Audited Request
the request linked in the comment will not work. You forgot to exclude other members. It should be something like:
SELECT * -- or whatever you want to return FROM conversation_user cu1 WHERE cu1.user_id = 32 AND EXISTS ( SELECT 1 FROM conversation_user cu2 WHERE cu2.conversation_id = cu1.conversation_id AND cu2.user_id = 3 ) AND NOT EXISTS ( SELECT 1 FROM conversation_user cu3 WHERE cu3.conversation_id = cu1.conversation_id AND cu3.user_id NOT IN (3,32) );
Which is similar to the other two queries, except that it will not return multiple rows if user_id = 3 is bound multiple times.
source share