【问题标题】:Checking if a set participants already exists in a Threaded Database schema检查一组参与者是否已存在于线程数据库模式中
【发布时间】:2013-06-04 18:24:43
【问题描述】:

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

所以我有三张桌子:

Conversations
    - conversationId

Messages:
   - messageId
   - conversationId
   - body

Participants
   - conversationId
   - userId

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    以下查询将告诉您具有给定用户集的所有对话(编码为单独的变量):

    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
    

    【讨论】:

    • 嗨,戈登,似乎在您的解决方案中,您必须提前知道用户的数量,因为您必须将它们放在一个变量中。此外,having 语句的数量取决于用户数量。有没有办法让它动态化,如果只有 1 个收件人甚至 20 个收件人应该适用?
    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多