Reputation: 12599
I've designed a database schema that allows for a Facebook style messaging system (without the feature of being able to edit messages). Here it is:
My idea was users send messages to a conversation, and not to another user. This way, users subscribe to a conversation, allowing for multiple user style chat.
A conversation
is like a room. If user bob and user joe start talking, a conversation will be created if one doesn't exist. Whenever 'bob' and 'joe' talk their messages will always have the same conversation_id
. This will allow me to return all their communication by getting all messages with their conversation_id
.
Multiple users can be a part of a conversation
. The conversation_users
table stores the the conversation_id
and the user_id
, which allows me to query the table to get All users who have the conversation_id X
.
The problem I'm having is I want to query: Give me the conversation_id used by Joe and Bob
, so I can then use this conversation_id
to return all of the messages between 'Joe' and 'Bob'.
How could I achieve this? I think I've missed something important out of my model, which is making this seem more complex than it needs to be. But I can't see what.
Upvotes: 0
Views: 91
Reputation: 108686
You need the intersection of the conversation_id values used by Joe, and by Bob.
How do you get the conversation_id values used by Joe?
SELECT cu.conversation_id
FROM Users u
JOIN Conversation_Users cu ON u.id = c.user_id
WHERE username = 'Joe'
You do the same for Bob, giving you two subqueries. Validate these; make sure they work correctly.
Then you do this:
SELECT cu.conversation_id
FROM Users u
JOIN Conversation_Users cu ON u.id = c.user_id
WHERE username = 'Joe'
AND cu.conversation_id IN
(
SELECT cu.conversation_id
FROM Users u
JOIN Conversation_Users cu ON u.id = c.user_id
WHERE username = 'Bob'
)
That gets you the list of conversation IDs involving the two users. Edit A JOIN
can also handle this logic, like so.
SELECT a.conversation_id
FROM (SELECT cu.conversation_id
FROM Users u
JOIN Conversation_Users cu ON u.id = c.user_id
WHERE username = 'Joe'
AND cu.conversation_id
) a
JOIN ( SELECT cu.conversation_id
FROM Users u
JOIN Conversation_Users cu ON u.id = c.user_id
WHERE username = 'Bob'
) b ON a.conversation_id = b.conversation_id
The first of those queries can be placed in a MySQL view, while the second one can't. Which one is faster? Hard to know without trying them both.
There may be more than one such conversation. If you want just one, you'll have to figure out how to select it.
You haven't left anything out of your model. It's just that the logic for this kind of intersection operation is made kind of subtle because MySQL doesn't have an INTERSECTION
operator.
Upvotes: 1