2014-09-06 95 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)) 

這是我想要的,但這一要求並沒有顯示沒有消息聯繫...