检查线程数据库模式中是否已存在集合参与者

时间:2013-06-08 15:43:58

标签: sql sql-server design-patterns database-design messaging

我正在为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.是否有更好的数据库方案以满足我的要求?

1 个答案:

答案 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