2015-02-07 71 views
0

我设计了一个数据库模式,允许使用Facebook风格的消息传递系统(没有能够编辑消息的功能)。那就是:我在模式中做错了什么?

enter image description here

我的想法是用户将消息发送到对话,而不是给其他用户。这样,用户订阅对话,允许多种用户风格的聊天。

A conversation就像一个房间。如果用户bob和用户joe开始通话,如果一个通话不存在,将会创建一个通话。每当'鲍勃'和'乔'说话他们的消息总是会有相同的conversation_id。这将允许我通过收到conversation_id的所有消息来返回他们的所有通信。

多个用户可以是conversation的一部分。 conversation_users表存储conversation_iduser_id,它允许我查询表得到All users who have the conversation_id X

我遇到的问题是我想查询:Give me the conversation_id used by Joe and Bob,所以我可以用这个conversation_id返回'Joe'和'Bob'之间的所有消息。

我怎么能做到这一点?我想我已经错过了一些重要的模型,这使得它看起来比需要的更复杂。但我看不到什么。

回答

1

您需要由Joe和Bob使用的conversation_id值的交集。

如何获取Joe使用的conversation_id值?

  SELECT cu.conversation_id 
      FROM Users u 
      JOIN Conversation_Users cu ON u.id = c.user_id 
      WHERE username = 'Joe' 

对Bob做同样的处理,给你两个子查询。验证这些;确保它们正常工作。

然后你这样做:

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' 
     ) 

,让你涉及两个用户的交谈ID列表。 编辑 A JOIN也可以像这样处理这个逻辑。

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 

这些查询的第一个可以放在MySQL视图中,而第二个查询不能。哪一个更快?很难知道没有尝试他们两个。

可能有多个这样的对话。如果你只想要一个,你必须弄清楚如何选择它。

你还没有离开你的模型。这只是因为这种交集操作的逻辑很微妙,因为MySQL没有INTERSECTION运算符。

+0

这是完美的。我需要刷我的SQL,因为如果没有你的建议,我需要一段时间才能在单个查询中弄清楚。感谢Ollie。 – 2015-02-07 16:02:19

+0

奥利,一个简单的问题,这可以通过一个Inner Join来完成吗?如果是这样更快? – 2015-02-07 22:53:55

+0

感谢Ollie。删除用户名,我重写你的第一个像这样:https://gist.github.com/jamesjeffery/f766813d5efcd041561e ...不知道是否这样做,只是现在检查您的编辑。 – 2015-02-07 23:46:10