简体   繁体   中英

Complex MySQL Conversation Group Query?

I have the following tables.

conversations
| id |
------
  1

and

conversationMembers
| id | conversationId | userId | email
---------------------------------------
   1         1            2      null  
   2         1           null    test@test.com
   3         1            7      null

Basically, I'm trying to construct a MySQL query that returns a row from the conversations table by an exact match of conversationMembers.

So, here's some examples of expected returns.

Let's say we want aa conversation id for a conversation between the exact following members: userId 2, userId 7, email test@test.com - This would see that in the conversationMembers table there's rows with the same conversation id and the exact match across all members of that conversation id that we're searching for. It would return conversations row with id 1.

Here's another example. We want a conversation id for a conversation between userId 2 and userId 7. This would see that there's not a conversation exclusively between userId 2 and userId 7, so it would not return anything.

And a final example. Let's say we want userId 7 and userId 9, this would also see there's no exclusive conversation between these 2 user id's and would return nothing.

What's the best way to go about doing it? I've played with subqueries but everything I've come up with doesn't seem to be able to handle the exact matching situation - I was having issues with selecting conversations for example - on userId 2 and 7 only (which should return nothing) and was getting conversationId 1 back, even though I didn't specify I wanted a conversation with test@test.com email as a part of it. I should only have gotten conversationId 1 back for if I searched on an exact match of all members in for conversationId.

One method is to use group by and having . This is nice because it is flexible with regards to what can be expressed. So, your first example is:

select conversionid
from conversationMembers
group by conversionid
having sum(userId = 2) > 0 and
       sum(userId = 7) > 0 and
       sum(email = 'test@test.com') > 0;

The condition being summed counts the number of members that match. The > 0 means there is at least one. For the second condition, the clause would be:

having sum(userId = 2) > 0 and
       sum(userId = 7) > 0 and
       sum(userId not in (2, 7)) = 0;

or alternatively:

select conversionid
from conversationMembers
group by conversionid
having sum(userId = 2) > 0 and
       sum(userId = 7) > 0 and
       count(distinct userId) = 2;

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM