I have 3 tables:
conversations
participants
contacts
participants is many to many between conversations and contacts. It has contact_id, and conversation_id.
I want to write a select query that takes one or more contact_id
values and returns a record from table conversations where there are rows matching ALL the passed in fields.
For example, I have:
conversations
id |
---|
1 |
contacts
id |
---|
1 |
2 |
participants
id | contact_id | conversation_id |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
If I call this query with [1, 2]
, it should return conversation
1. If I call it with [1]
, it should return nothing.
How do I do that?
I have tried using a subquery, but I would need to know the conversation id in the subquery, which will execute first, without the context.
2
Answers
Can do this with a combination of SQL JOINs and GROUP BY with HAVING clause to filter the conversations that have all the specified contact_id values in the participants table
e.g
the above query will return the conversation(s) that have all the specified contact_ids. If you want to search for different sets of contact_ids, just adjust the IN clause and the count in the HAVING clause accordingly.
From the described output, it appears that the query is intended to return conversations where all of the specified contacts, and only those contacts, are participants (which is slightly different from the stated requirement of "returns a record from table conversations where there are rows matching ALL [selected contacts]"). There are, of course, many ways to construct a query to satisfy such a request. The following query uses an array as presented in the original post:
Note that this query protects against redundant contact IDs in the criteria array and also determines the number of distinct contact IDs instead of requiring the count to be explicitly declared.