MySQL 8.0分组取每人最新预约并按姓名降序排列的查询问题
问题根因
你原有SQL失效是因为MySQL优化器的默认行为:当子查询没有写LIMIT限制时,优化器会直接忽略子查询内部的ORDER BY排序逻辑,不会保证子查询输出的结果按预约日期倒序排列,因此外层GROUP BY取分组第一条时,拿到的并不是最新的预约记录。
额外提醒:依赖GROUP BY直接取非聚合字段的写法本身就不符合SQL标准,当MySQL开启ONLY_FULL_GROUP_BY模式时这类语句会直接报错,生产环境不建议使用这种写法。
推荐实现(MySQL 8.0+ 适用)
MySQL 8.0原生支持窗口函数,用ROW_NUMBER()实现分组取最新记录逻辑最清晰、性能最稳定,语句如下:
SELECT Name, Appointment FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Appointment DESC) AS row_seq FROM `Table` ) AS temp WHERE row_seq = 1 ORDER BY Name DESC;
写法说明
- 子查询里通过
PARTITION BY Name按人员分组,每组内按预约日期倒序给每行打序号,最新的预约记录序号固定为1 - 外层过滤序号为1的记录,再按姓名倒序排序就能得到预期结果
- 如果同一个人存在多条日期完全相同的最新预约记录,需要把所有同日期记录都返回的话,把
ROW_NUMBER()替换为RANK()即可
兼容写法(全MySQL版本适用)
如果需要兼容低版本MySQL,可以通过聚合最大日期后关联原表的方式实现:
SELECT t.Name, t.Appointment FROM `Table` t JOIN ( SELECT Name, MAX(Appointment) AS latest_appointment FROM `Table` GROUP BY Name ) AS tmp ON t.Name = tmp.Name AND t.Appointment = tmp.latest_appointment ORDER BY t.Name DESC;
这种写法的特点是如果同一个人有多条和最大预约日期相同的记录,会全部返回,可根据实际业务需求选择。
内容的提问来源于stack exchange,提问作者SomebodyOnEarth
相关产品推荐
相关产品推荐

