2012-06-09 56 views
1

我已經爲用戶創建了一個消息系統,允許用戶將消息發送給另一個消息。在mysql中以特定格式顯示消息php

爲此我創建了兩個表格。

conversation(conversation_id,user_id1,user_id2) 
    messages(message_id,conversation_id,sender_id,receiver_id,message,created_time) 

如果用戶正在談論第一次,一個conversation_id將與user_id1(誰發起聊天)和user_id2創建(以誰user_id1在發送消息)

信息表將包含有關消息的所有信息。

現在我想要創建一個消息摘要頁面,其中登錄用戶可以查看他的所有會話列表,其他用戶按照created_time排序,按conversation_id排序。

下面是表中的數據:

conversation_id | user_id1 | user_id2 
    1    100  103 
    2    101  103 
    3    103  102   


message_id| conversation_id| sender_id| receiver_id| message | created_time 
    1    1   100  103   MSG A 2012-06-08 08:38:57 
    2    1   103  100   MSG B 2012-06-08 08:39:40 
    3    2   101  103   MSG C 2012-06-08 08:40:20 
    4    3   102  103   MSG D 2012-06-08 08:41:10 

而且這裏是輸出什麼,我在尋找:讓我們的用戶說已登錄的ID爲:103

conversation_id| conversation_with | last_message | created_time 
     3    102    MSG D   2012-06-08 08:41:10 
     2    101    MSG C   2012-06-08 08:40:20 
     1    100    MSG B   2012-06-08 08:39:40 

所以這個輸出是按created_time排序,按conversation_id分組,並在conversation_with中顯示用戶的id,以及誰正在進行對話。

有人可以提供MySQL查詢我需要得到這個輸出。

回答

1

這是一個有趣的。所以,你需要解決三個主要問題。

  1. 替代conversation_with列取決於所需用戶在兩列之間出現的位置。
  2. greatest-n-per-group找到最近的message
  3. least-n-per-group找到最早的消息created_time

我通過查詢兩次,交替user_id柱,unioning的結果,然後通過created_time訂購聯合在一起的結果要解決的第一個。我想我可以用一個查詢來解決這個問題,而且沒有聯盟,但是現在它可以工作。

2和3有一點涉及。下面是與查詢SQL小提琴:http://sqlfiddle.com/#!2/bf2b7/1

TL; DNR

select * from (
    select c.conversation_id, c.user_id2 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c 
     join messages as m1 on c.conversation_id = m1.conversation_id 
     left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
             and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id)) 
     join messages as m3 on c.conversation_id = m3.conversation_id 
     left outer join messages as m4 on (c.conversation_id = m4.conversation_id 
             and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id)) 
    where user_id1 = 103 and m2.message_id is null and m4.message_id is null 
    union all 
    select c.conversation_id, c.user_id1 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c 
     join messages as m1 on c.conversation_id = m1.conversation_id 
     left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
             and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id)) 
     join messages as m3 on c.conversation_id = m3.conversation_id 
     left outer join messages as m4 on (c.conversation_id = m4.conversation_id 
             and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id)) 
    where user_id2 = 103 and m2.message_id is null and m4.message_id is null 
             ) as conversations 
order by created_time desc 
+0

太好了!你已經做到了!如果我們考慮速度和性能呢? – Jadzia

+0

大量的性能測試需要完成,但通常「最大/最小每組數」非常有效。你需要在'created_time'上添加和索引,如果你在消息和會話之間創建了一個外鍵,那麼這些外鍵也會被索引。 – HackedByChinese

+0

我將SQL小提琴更新爲帶有一些主鍵,索引和外鍵的版本。 – HackedByChinese