1

我正在为 Web 应用程序创建一个线程消息传递系统,就像在 Facebook 的消息传递系统中一样。我在 StackOverflow 中遵循了线程消息的其他数据库方案,但我没有在他们的要求中看到我的要求。

所以我有三张桌子:

Conversations
    - conversationId

Messages:
   - messageId
   - conversationId
   - body

Participants
   - conversationId
   - userId

Conversations如果用户创建新对话,则在表中创建新的对话记录。消息的正文以及随后的回复都存储在Messages带有 conversationId 的表中。最后,将参与者(发送者和 1 个或多个接收者)添加到Participants表中。

例如,A 人向 B 人发送消息。如果 A 和 B 之间的对话尚不存在,则应创建一个具有新 ID 的新对话。但是如果 A 和 B 已经有一条记录,它应该只是将消息添加到Messages具有现有对话 ID 的表中。如果 A 发送 B 和 C,那是一个新线程,不应包含在最后一次对话中。

如果用户创建一个新的对话给他已经有过对话的人(人 A 和 B 已经有一个现有的对话),消息传递应用程序不应该创建另一个对话 Id,而只是获取所有参与者都存在的对话 Id。

我想知道的是如何找出我应该将新消息附加到哪个对话。我应该如何制定我的查询以获取与确切参与者的对话 ID?如果参与者的 userIds 不匹配,它应该返回 0。是否有更好的数据库方案来满足我的要求?

4

1 回答 1

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
于 2013-06-08T15:49:40.367 回答