2017-11-18 49 views
2

您好,我正在使用以下查詢從每個唯一對話中選擇最新消息。除了當我嘗試集成INNER JOIN以嘗試在users表中鏈接用戶的user_id及其username時,所有內容都可以正常工作。無法在我的查詢中集成INNER JOIN

我已經嘗試過幾乎所有的組合來集成INNER JOIN,所以我決定將它從正在工作的查詢中分離出來,直到我獲得幫助。

我做了一個小提琴http://sqlfiddle.com/#!9/a9bbc/1我只想USER_ID右邊打印用戶的用戶名

SELECT message_id, 
     msg, 
     user_id 
FROM messages 
    JOIN (SELECT user_id, 
       Max(dat) m 
     FROM ((SELECT message_id, 
         recipient_id user_id, 
         dat 
        FROM messages 
        WHERE owner_id = 1) 
       UNION 
       (SELECT message_id, 
         owner_id user_id, 
         dat 
        FROM messages 
        WHERE recipient_id = 1)) t1 
     GROUP BY user_id) t2 
    ON ((owner_id = 1 
      AND recipient_id = user_id) 
      OR (owner_id = user_id 
       AND recipient_id = 1)) 
     AND (dat = m) 
ORDER BY dat DESC 

users.username INNER JOIN users ON messages.user_id = users.user_id; 
+0

whats users.username here -schemaname.tablename or tablename.column name? –

+0

tablename.column – Julian

+0

你應該使用連接與表,你在這裏做錯了。它應該是messages上的內部消息加入用戶.user_id = users.User_Id –

回答

1

如果messages.message_idAUTO_INCREMENT PRIMARY KEY列,這將可能是能收到理想的結果的最快方法:

select m.message_id, m.msg, u.username, 
    case sub.other_user_id 
    when m.owner_id  then 'received from' 
    when m.recipient_id then 'sent to' 
    end as direction 
from (
    select other_user_id, max(message_id) as message_id 
    from (
    select recipient_id as other_user_id, max(message_id) as message_id 
    from messages 
    where owner_id = @uid 
    group by recipient_id 

    union all 

    select owner_id as other_user_id, max(message_id) as message_id 
    from messages 
    where recipient_id = @uid 
    group by owner_id 
) sub 
    group by other_user_id 
) sub 
join messages m on m.message_id = sub.message_id 
join users u on u.user_id = sub.other_user_id 
order by sub.message_id desc 

我我也添加了列direction。通過這種方式,您將知道該消息是否已發送或接收。其結果將是這樣的:

| message_id |                msg | username |  direction | 
|------------|------------------------------------------------------------------|----------|---------------| 
|   9 | You should also see this           | User3 |  sent to | 
|   8 | you should Now see this instead even with the owner_id flipped.. | User2 | received from | 

http://sqlfiddle.com/#!9/a9bbc/34

注意,您可以從usersmessages表的SELECT子句中仍然添加任何列。

爲了快速獲得此查詢,您需要索引messages(owner_id, recipient_id)messages(recipient_id, owner_id)

+0

非常優雅的解決方案 – Julian

+0

2發送到3(不工作):[小提琴](http:// sqlfiddle .com /#!9/0858dd/1) – Zorkolot

+1

@Zorkolot如果User2向User3發送消息,他們(通常)不希望User1看到它:-)請注意'@ uid'必須由'正在發送請求的用戶的user_id。在這種情況下,它是User1的'user_id = 1'。我們只希望看到發送或接收來自該用戶的消息。 –

0

當你加入任何表或子查詢時,你確實需要在所有列引用中包含表名或表別名。我把最大的dat改爲maxdat,所以我可以用m來表示消息。

SELECT 
     m.message_id 
    , m.msg 
    , m.user_id 
FROM messages m 
JOIN (
     SELECT 
      user_id 
      , MAX(dat) maxdat 
     FROM (
      (SELECT 
        message_id 
       , recipient_id user_id 
       , dat 
      FROM messages 
      WHERE owner_id = 1) 
      UNION 
      (SELECT 
        message_id 
       , owner_id user_id 
       , dat 
      FROM messages 
      WHERE recipient_id = 1) 
    ) t1 
     GROUP BY 
      user_id 
) t2 ON (
     (m.owner_id = 1 AND m.recipient_id = t2.user_id) 
     OR (m.owner_id = t2.user_id AND m.recipient_id = 1) 
     ) 
     AND (m.dat = t2.maxdat) 
ORDER BY 
     m.dat DESC 
0

如果我理解正確,您需要發送或接收者爲「1」和關聯用戶名的最新消息。

這表明:

select m.*, ur.username as recipient_name, us.username as sender_name 
from messages m join 
    users ur 
    on m.recipient_id = ur.user_id join 
    users us 
    on m.sender_id = us.user_id 
where m.date = (select max(m2.dat) 
       from messages m2 
       where 1 in (m2.recipient_id, m2.sender_id) 
       ) and 
     1 in (m.recipient_id, m.sender_id); 

編輯:

你的SQL小提琴基於上述認識是不正確的。你要考慮對受助人的,所以我想你想:

select m.*, ur.username as recipient_name, us.username as sender_name 
from messages m left join 
    users ur 
    on m.recipient_id = ur.user_id left join 
    users us 
    on m.owner_id = us.user_id 
where m.dat = (select max(m2.dat) 
       from messages m2 
       where (m2.recipient_id, m2.owner_id) = (m.recipient_id, m.owner_id) or 
        (m2.recipient_id, m2.owner_id) = (m.owner_id, m.recipient_id) 
      ) and 
     1 in (m.recipient_id, m.owner_id); 

Here是SQL小提琴。

如果對的排序是進口(因此(1, 2)(2, 1)不同去除最裏面where子句中的第二個條件。

+0

謝謝你的回覆,很遺憾我在'字段列表'中有'未知列'ur.name'的錯誤,我在編輯中添加了一些示例數據。 – Julian

+0

嘗試你的新編輯,但仍然無濟於事...我做了一個小提琴[鏈接](http://sqlfiddle.com/#!9/14498d/2)我只想用戶名,而不是他們的user_id – Julian

0

你需要與用戶表加入您的最終結果,並得到用戶的價值。基於USER_ID用戶名試試這個:。

SELECT messages.message_id, 
    messages.msg, 
    users.user_id, 
    users.username 
FROM users, messages 
    JOIN (SELECT user_id, 
      Max(dat) m 
    FROM ((SELECT message_id, 
        users.username, 
        recipient_id user_id, 
        dat 
       FROM messages 
       INNER JOIN users ON messages.recipient_id = users.user_id 
       WHERE owner_id = 1) 
      UNION 
      (SELECT message_id, 
        users.username, 
        owner_id user_id, 
        dat 
       FROM messages 
       INNER JOIN users ON messages.owner_id = users.user_id 
       WHERE recipient_id = 1)) t1 
    GROUP BY user_id) t2 
ON ((owner_id = 1 
     AND recipient_id = user_id) 
     OR (owner_id = user_id 
      AND recipient_id = 1)) 
    AND (dat = m) 
WHERE users.user_id = messages.user_id 
ORDER BY dat DESC 
+0

謝謝你你的迴應,但我得到了這個錯誤'未知列'messages.user_id'在'where子句'' – Julian

1

我認爲這是正確的......終於沒有開始後,存在過濾掉反應..內部查詢抓住最近的談話這應該符合預期輸出。

SELECT dT.maxid AS message_id 
     ,(SELECT msg FROM messages M WHERE M.message_id = dT.maxid) AS message_id 
     ,(SELECT username FROM users U WHERE U.user_id = dT.owner_id) AS user_id  
    FROM ( 
     SELECT MAX(message_id) as maxid 
       ,owner_id 
       ,recipient_id 
      FROM messages M 
     GROUP BY owner_id, recipient_id 
     ) AS dT 
WHERE NOT EXISTS(SELECT * 
        FROM messages M2 
        WHERE M2.recipient_id = dT.owner_id 
        AND M2.owner_id = dT.recipient_id 
        AND M2.message_id > dT.maxid) 
ORDER BY dT.maxid   

生成輸出:

message_id message_id            user_id 
8   you should Now see this instead even with the   User2 
      owner_id flipped.. The users_id in the query is 1 
      and it gets the conversation with user_id 2 
9   You should also see this        User1 

fiddle

+0

謝謝你的迴應,我做了一個[小提琴](http://sqlfiddle.com/#!9/93e120/ 1)...我想要的是'user_id'在右側打印用戶名' – Julian

+0

@Julian這可能是[小提琴](http://sqlfiddle.com/#!9/5ed6e8/3/ 0) – Zorkolot

+0

我剛剛意識到你的解決方案打印出正確的答案,但不是我正在尋找的東西。我更新了我正在尋找的[fiddle](http://sqlfiddle.com/#!9/a9bbc/1)...我需要它在對話中顯示最重新發送的消息,而不管'owner_id ''或'recipient_id'查詢中的user_id是'1',因此它會在每次對話中得到最新消息。再次感謝 – Julian