得到一个查询的两个版本。两者都不符合我的需要。。
正在尝试返回所有用户,以及将发送到该用户的OR的最新消息的时间。另一个标志显示最后一条消息是否是来自当前行中用户的(因此他们是否在"等待响应")。
最后,需要对整个结果集进行排序,使这些用户首先"等待响应",然后在最新消息发布时进行排序。
版本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,问题基本相同——由于没有MAX()聚合函数,DISTINCT会挑出联接中发现的第一条消息(不是最近的消息)。
有没有一种简单的方法可以确保最新消息在这里成为目标?
附言:它需要在MySQL 4中工作;)
最简单的方法应该是:
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
然而,需要强调的是,尽管可能会起作用,但不能保证能起作用——分组select语句中包含的未聚合、未分组的值通常是按顺序排列的值,但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