2012-04-10 76 views
1

我正在构建基于mysql的聊天应用程序。只显示mysql中的唯一条目

我的数据库架构有如下表,

 Users    Messages 
    ================= ================= 
     id     id 
     screen_name  message 
          from 
          to 
          timestamp 

的距离,并在信息表中的字段包含发送和接收的每封邮件的用户ID的。

我想显示用户($ id)和他们的朋友之一($朋友)之间的所有消息。我的查询如下:

$query = "SELECT messages.* , users.screen_name FROM users CROSS JOIN messages "; 
$query .= "ON (messages.to = $id AND messages.from = $friend) "; 
$query .= "OR (messages.to = $friend AND messages.from = $id)"; 

问题是每个消息在结果表中都是两次。

我试过使用DISTINCT,但它不是在这种情况下工作,或者我用它错了。

我的查询应该为了让两个用户之间的每条消息只有一次?

+0

'GROUP BY messages.id'? – jensgram 2012-04-10 13:29:51

+0

似乎是在做的伎俩。你能否简单地在答案中解释一下,以便我可以授予代表? – ppp 2012-04-10 13:32:02

+2

您正在选择'messages。*'。使用'SELECT DISTINCT',如果这些字段中的任何一个不同(不管消息是否相同),那么你将得到两行。我建议你不要使用'SELECT *',而是明确地选择你实际需要的每个单独的字段。有关更多信息,请参见[本文](http://stackoverflow.com/questions/321299/what-is-the-reason-not-to-use-select)。 – Travesty3 2012-04-10 13:34:34

回答

3

像这样的东西应该做的伎俩:

SELECT 
    messages.*, 
    users_from.screen_name AS from_screen_name, 
    users_to.screen_name AS to_screen_name 
FROM 
    messages 
    JOIN users AS users_from ON messages.from = users_from.id 
    JOIN users AS users_to ON messages.to = users_to.id 
WHERE 
    (messages.to = $id AND messages.from = $friend) 
    OR (messages.to = $friend AND messages.from = $id) 

这样做是joing的“用户”表两次,一次是在“到”列和“从”列中的第二次。

+0

这个答案也可以。 – ppp 2012-04-10 13:52:33

1

@Travesty3已经建议DISTINCT关键字将只排除重复行,其中全部字段等于另一行。因此,DISTINCT关键字不是这里要走的路。

但是,您可以执行的操作只是简单地为GROUP BY messages.id,以便每个消息ID只能获得一行(但不能保证两行中的哪一行将被排除)。

+0

这似乎工作得很好,但1月份提出的双连接也是如此。两者之间的性能有差异吗? – ppp 2012-04-10 13:54:17

+0

@AnPel鉴于用于'JOIN'和'GROUP BY'的字段被索引,我怀疑这两个表现都令人满意。您可以做的是使用实际数据集上的示例查询进行基准测试。 – jensgram 2012-04-10 13:59:21