SQL查询GROUP BY与ORDER BY联用报语法错误,如何获取最新消息?
解决MySQL GROUP BY语法错误并获取指定客户的最新消息
首先,你的语法错误原因很明确:在SQL语句中,GROUP BY子句必须放在ORDER BY子句之前。你原来的语句把ORDER BY放在了GROUP BY前面,这违反了MySQL的语法规则,所以才会抛出1064错误。
但即使你调整了顺序,直接用GROUP BY customer.cus_id也无法正确获取每个客户的最新消息——因为禁用ONLY_FULL_GROUP_BY后,MySQL会返回每组的任意一条记录,而不是最新的那条。下面是两种可靠的解决方案:
方法1:子查询匹配最新消息时间(兼容所有MySQL版本)
先找出每个目标客户(31、26)与25号客户之间的最新消息发送时间,再通过这个时间关联回原表,拿到完整的消息和客户信息:
SELECT c.cus_id, c.fname, c.lname, c.image, m.message, m.msg_id, m.from_cus, m.to_cus, m.sent_time FROM customer c INNER JOIN message m ON c.cus_id = m.from_cus OR c.cus_id = m.to_cus INNER JOIN ( -- 子查询:获取每个目标客户与25号的最新消息时间 SELECT CASE WHEN from_cus = 25 THEN to_cus ELSE from_cus END AS target_cus, MAX(sent_time) AS latest_sent_time FROM message WHERE (from_cus = 25 OR to_cus = 25) AND (from_cus IN (31,26) OR to_cus IN (31,26)) GROUP BY target_cus ) latest_msg ON ( (m.from_cus = 25 AND m.to_cus = latest_msg.target_cus) OR (m.to_cus = 25 AND m.from_cus = latest_msg.target_cus) ) AND m.sent_time = latest_msg.latest_sent_time WHERE c.cus_id IN (31,26) ORDER BY m.sent_time DESC;
方法2:窗口函数(MySQL 8.0+ 推荐)
如果你的MySQL版本是8.0或以上,用窗口函数会更简洁直观。我们用ROW_NUMBER()按客户分组、按发送时间倒序排名,然后取每组的第一条(也就是最新消息):
WITH ranked_messages AS ( SELECT c.cus_id, c.fname, c.lname, c.image, m.message, m.msg_id, m.from_cus, m.to_cus, m.sent_time, -- 按目标客户分组,按消息时间倒序生成排名 ROW_NUMBER() OVER ( PARTITION BY c.cus_id ORDER BY m.sent_time DESC ) AS rn FROM customer c INNER JOIN message m ON c.cus_id = m.from_cus OR c.cus_id = m.to_cus WHERE c.cus_id IN (31,26) AND (m.from_cus =25 OR m.to_cus =25) ) SELECT cus_id, fname, lname, image, message, msg_id, from_cus, to_cus, sent_time FROM ranked_messages WHERE rn = 1 ORDER BY sent_time DESC;
额外提示
- 方法1适配所有MySQL版本,方法2更简洁但需要8.0及以上版本,根据你的环境选择即可。
- 两种方法都能确保你获取到31、26号客户与25号客户之间的最新单条消息,不会出现随机返回记录的问题。
内容的提问来源于stack exchange,提问作者Akshay Singla
相关产品推荐
相关产品推荐

