2014-09-06 64 views
0

我有3个表:SQL请求多个左连接和零

* User : iduser , pseudo, password, email, admin 
* Message : idmessage, sender, recipient, time, message 
* Contact : user1, user2 (both refer to id user) 

我正在寻找一种方式来获得接触与最后的消息特定ID用户发送或接收邮件的时间。 (如果可能,请按时间排序)

在联系人表中,联系人只有一个条目,因此如果user1和user2是朋友,则该表中只有一个条目(user1:iduser1,user2:iduser2 )。

我可以接触:

SELECT iduser, pseudo, email 
FROM user WHERE iduser!=/*ID GENERATED BY PHP*/ 
AND (
iduser 
IN ( 
    SELECT user1 
    FROM contact c1 
    WHERE c1.user1=user.iduser 

    UNION 

    SELECT user2 
    FROM contact c2 
    WHERE c2.user2=user.iduser)) 

我可以联系和消息,但仅适用于谁在数据库中至少有一个消息接触。我会使用LEFT JOIN,但问题是iduser可以与发件人或收件人匹配,所以我不能只执行LEFT JOIN所需的一个关系。因此,此请求仅适用于有邮件的联系人,您是否可以帮助我调整此请求以获取来自用户的所有联系人,并只有最后一条邮件存在?

这是我用来获取与信息联系方式只有

SELECT iduser, pseudo, email, idmessage, message, time 
FROM user, message m1 
WHERE (sender=iduser OR recipient=iduser) 
AND iduser!=4 AND (iduser 
IN (SELECT user1 
    FROM contact c1 
    WHERE c1.user1=user.iduser 

    UNION 

    SELECT user2 
    FROM contact c2 
    WHERE c2.user2=user.iduser) 
    ) 
    AND time=(SELECT MAX(time) 
      FROM message m2 
      WHERE (sender=user.iduser 
        OR recipient=user.iduser)) 

结果我早就:

IDuser Pseudo Email  Message Time 
1   Jean  [email protected] Hi!  2014-03-04 15:00 
2   Luc  [email protected] Hello! 2014-03-05 23:00 
4   Paul  [email protected] Bye!  2014-03-06 15:00 
6   Tom  [email protected] Hey!  2014-03-07 14:00 

我解释什么我会。有一个由PHP 生成的IDUser我会有:用户的朋友给出的Id,伪和电子邮件。它符合我的第一个要求。但是我会得到更多的信息,对于给定用户的所有联系人,我会得到行用户的最后一条消息。如果联系人没有发送或收到任何消息,我也会让用户进入列表。

+0

你可以,你知道,做'LEFT JOIN为C ON(u.id = C接触。 user1或u.id = c.user2)'这有帮助吗?如果不是,请给出一个更清晰的结果集示例。 – 2014-09-06 13:13:41

+0

我试图用这个解决方案,但它不起作用,也许我找不到正确的方式来使用它。我编辑我的帖子来解释更多。谢谢 – X4V18 2014-09-06 13:23:06

+0

我在你的表定义中看不到列'iduser'。什么是'iduser'? – Bohemian 2014-09-06 13:25:21

回答

0

你可以得到所有联系人之间的消息像这样的东西:

select * 
from users u join 
    contacts c 
    on c.user1 = u.id or c.user2 = u.id left join 
    messages m 
    on m.sender = c.user1 and m.recipient = c.user2 or 
     m.sender = c.user2 and m.recipient = c.user1 
where u.id = @YOURID; 

为了获得最新的需要多一点的挂羊头卖狗肉。我认为这是你想要的:

select u.iduser, c.*, m.* 
from user u join 
    contact c 
    on c.user1 = u.iduser or c.user2 = u.iduser left join 
    message m 
    on m.sender = c.user1 and m.recipient = c.user2 or 
     m.sender = c.user2 and m.recipient = c.user1 
where not exists (select 1 
        from message m2 
        where (m2.sender = m.sender and m2.recipient = m.recipient or 
         m2.recipient = m.sender and m2.sender = m.recipient 
         ) and 
         m2.time > m.time 
       ); 

Here是这个查询的SQL小提琴。

+0

谢谢你的回答,我这样试过,但是仍然有2个问题: *如果一个联系人没有任何消息,联系人将不会在结果集中
*一个用户有多个条目 通过联系最后一条消息我只有一个条目。 (我可能没有解释到底会发生什么,对于混淆抱歉) – X4V18 2014-09-06 13:38:53

+0

@ X4V18。 。 。'不存在'应该处理这些情况。你可以设置一个SQL小提琴吗? – 2014-09-06 14:33:22

+0

当然,http://sqlfiddle.com/#!2/6b5fb/2 你帮了我很多,我离正确的要求不远了。随着你的第一个请求我有太多的消息,所以我尝试通过iduser分组有max(时间),它的工作,但我没有空条目。 – X4V18 2014-09-06 14:43:41

0
SELECT iduser, pseudo, email, idmessage, message, time FROM user, message m1 WHERE (sender=iduser OR recipient=iduser) AND iduser!=4 AND (iduser IN (SELECT user1 FROM contact c1 WHERE c1.user1=user.iduser UNION SELECT user2 FROM contact c2 WHERE c2.user2=user.iduser)) AND time=(SELECT MAX(time) FROM message m2 WHERE (sender=user.iduser OR recipient=user.iduser)) 

这是我想要的,但这一要求并没有显示没有消息联系...