我正在为Web应用程序创建一个线程化的消息传递系统,就像Facebook的消息传递系统一样。我在StackOverflow中跟踪了其他数据库方案的线程消息,但我还没有看到他们的要求。
所以我有三张桌子:
Conversations
- conversationId
Messages:
- messageId
- conversationId
- body
Participants
- conversationId
- userId
如果用户创建新会话,则会在Conversations
表中创建新的会话记录。消息正文以及后续回复将与conversationId一起存储在Messages
表中。最后,参与者(发件人和一个或多个接收者)被添加到Participants
表中。
例如,人A向人B发送消息。如果A和B之间的对话尚不存在,则应使用新ID创建新对话。但是,如果A和B已经有记录,它应该只使用现有的会话ID将消息添加到Messages
表。如果A发送B和C,那就是新线程,不应该包含在最后一个会话中。
如果用户与已经与之交谈的人(人A和B已经有现有对话)创建了新对话,则消息应用不应创建另一个对话ID,而只是与所有现有参与者一起获得对话ID。
我想知道的是如何找出我应该添加新消息的对话。我应该如何制定我的查询以获得与确切参与者的对话ID?如果参与者userIds不匹配,则应返回0.是否有更好的数据库方案以满足我的要求?
答案 0 :(得分:0)
以下查询将告诉您具有给定用户集的所有会话(编码为单独的变量):
select conversation_id
from Participants p
group by conversation_id
having sum(case when user_id = @User1 then 1 else 0 end) > 0 and
sum(case when user_id = @User2 then 1 else 0 end) > 0 and
. . .
sum(case when user_id not in (@user1, @user2, . . .) then 1 else 0 end) = 0
第一个条款检查所有用户是否在谈话中。最后检查他们是唯一的。如果您想返回0
而不是没有行,可以使用聚合来执行此操作:
select coalesce(max(conversation_id), 0)
from Participants p
group by conversation_id
having sum(case when user_id = @User1 then 1 else 0 end) > 0 and
sum(case when user_id = @User2 then 1 else 0 end) > 0 and
. . .
sum(case when user_id not in (@user1, @user2, . . .) then 1 else 0 end) = 0