2012-01-25 26 views
2

有兩個版本的查詢。無論是做完全是我需要..在MySQL的JOIN內部進行排序 - 每個用戶的最新信息

試圖返回的所有用戶,與最新消息的時間一起發送要麼或從用戶。一個額外的標誌顯示最後一條消息是當前行中的用戶(因此他們是否'等待迴應')。

最後,需要對整個結果集進行排序,讓這些用戶首先等待響應,然後在最新消息的時間點排序。

版本1:

SELECT `users`.*, 
MAX(`messages`.`time_sent`) AS `_message_time_sent`, 
(`messages`.`user_id` = `users`.`id`) AS `_message_awaiting_response` 
FROM `users` LEFT JOIN `messages` 
ON (`messages`.`user_id` = `users`.`id` OR `messages`.`to_user_id` = `users`.`id`) 
GROUP BY `users`.`id` 
ORDER BY `_message_awaiting_response` DESC, `messages`.`time_sent` DESC 

版本1的問題:從哪個消息最早出現在之前的加入「_message_sent_time」是正確的(通過MAX),但「_message_awaiting_response」標誌總是派生MAX()發生,這可能不是最新的消息。

版本2:

SELECT DISTINCT `users`.*, 
`messages`.`time_sent` AS `_message_time_sent`, 
(`messages`.`user_id` = `users`.`id`) AS `_message_awaiting_response` 
FROM `users` LEFT JOIN `messages` 
ON (`messages`.`user_id` = `users`.`id` OR `messages`.`to_user_id` = `users`.`id`) 
GROUP BY `users`.`id` 
ORDER BY `_message_awaiting_response` DESC, `messages`.`time_sent` DESC 

隨着2.0版本,這個問題主要是相同的 - 因爲那裏是沒有MAX()聚合函數,第一條消息中加入(不是最近的)發現的由DISTINCT單出。

有沒有一種簡單的方法來確保最新消息在這裏被定位?

P.S.它需要在MySQL 4的工作;)

+0

哎呀,我的壞..想表明誰去過用戶等待最早的迴應第一,所以第二個命令應該是'messages'.'time_sent' ASC –

回答

2

最簡單的方法來做到這一點應該是:

SELECT * FROM 
(SELECT `users`.*, 
     `messages`.`time_sent` AS `_message_time_sent`, 
     (`messages`.`user_id` = `users`.`id`) AS `_message_awaiting_response` 
FROM `users` 
LEFT JOIN `messages` 
     ON `messages`.`user_id` = `users`.`id` OR 
      `messages`.`to_user_id` = `users`.`id` 
ORDER BY `users`.`id`, `messages`.`time_sent` DESC 
) V 
GROUP BY V.`id` 
ORDER BY `_message_awaiting_response` DESC, `_message_time_sent` DESC 

但是,應該強調的是,雖然這可能工作,它不能是保證去工作 - 分組選擇語句中包含的未分組的未分組值通常是按順序排列的,但MySQL文檔並未將此行爲描述爲可靠。

,應始終工作(前提是給定的用戶不具有相同的時間戳的多個消息),另一種方法是:

select u.*, 
     m.`time_sent` AS `_message_time_sent`, 
     (m.`user_id` = u.`id`) AS `_message_awaiting_response` 
from `users` u 
left join (select `user_id`, max(`time_sent`) AS `last_sent` 
      from (select `time_sent`, `user_id` from `messages` union all 
       select `time_sent`, `to_user_id` `user_id` from `messages`) v 
      group by `user_id`) lm 
     on u.`user_id` = lm.`user_id` 
left join `messages` m 
     ON m.`time_sent` = lm.`last_sent` and 
      lm.`user_id` in (m.`user_id`, m.`to_user_id`) 
ORDER BY `_message_awaiting_response` DESC, `_message_time_sent` DESC 
+0

這看起來很適合我。你能詳細說明爲什麼這可能無效嗎? –

+0

太好了,看起來不錯.. GROUP BY需要V.'id'然而..謝謝! –

+0

@BenLee它的工作原理是因爲子查詢在GROUP BY發生之前首先正確地進行了排序.. –

相關問題