MySQL如何查询每个日期下各id_sequence对应的最新记录
问题背景
要在MySQL中编写SQL语句,从包含id、id_sequence、date三个字段的数据表中,取出每个日期下、每个id_sequence分组里id值最大的记录,也就是每个日期对应各序列的最新一条数据。
- 样例表数据:
| id | id_sequence | date |
|---|---|---|
| 1 | 1 | 2022-06-27 |
| 2 | 1 | 2022-06-27 |
| 3 | 1 | 2022-06-27 |
| 4 | 2 | 2022-06-27 |
| 5 | 2 | 2022-06-27 |
| 6 | 1 | 2022-06-28 |
| 7 | 1 | 2022-06-28 |
| 8 | 2 | 2022-06-28 |
| 9 | 2 | 2022-06-28 |
- 预期输出结果:
| id | id_sequence | date |
|---|---|---|
| 3 | 1 | 2022-06-27 |
| 5 | 2 | 2022-06-27 |
| 7 | 1 | 2022-06-28 |
| 9 | 2 | 2022-06-28 |
之前尝试直接对id_sequence使用MAX(id)函数编写查询,无法返回正确结果,以下是可直接运行的正确实现写法。
正确SQL写法
写法1:通用关联查询(兼容所有MySQL版本)
核心逻辑是先按date和id_sequence分组,算出每个分组对应的最大id值,再通过关联条件匹配回原表,取出最大id对应的完整记录,MySQL 5.x全版本支持:
SELECT t.* FROM 替换为你的实际表名 t INNER JOIN ( SELECT `date`, id_sequence, MAX(id) AS max_id FROM 替换为你的实际表名 GROUP BY `date`, id_sequence ) AS group_tmp ON t.id = group_tmp.max_id AND t.`date` = group_tmp.`date` AND t.id_sequence = group_tmp.id_sequence;
写法2:窗口函数写法(仅支持MySQL 8.0及以上版本)
如果使用的是MySQL 8.0及以上版本,可以直接用ROW_NUMBER()窗口函数简化逻辑,按分组维度对同组记录按id倒序编号,取每组编号为1的记录即可:
SELECT id, id_sequence, `date` FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY `date`, id_sequence ORDER BY id DESC) AS row_num FROM 替换为你的实际表名 ) t WHERE row_num = 1;
注意:
date是MySQL保留关键字,SQL中引用该字段时必须用反引号`包裹,否则会触发语法错误,将代码里的表名占位符替换为实际业务表名即可直接运行。
直接使用MAX(id)写法的问题
如果直接写SELECT id, id_sequence, date, MAX(id) FROM 表名 GROUP BY date, id_sequence,在MySQL 5.7及以上默认开启ONLY_FULL_GROUP_BY模式的环境中会直接报语法错误;就算手动关闭该校验规则,返回的非聚合字段值也只是分组内随机读取的,不会和MAX(id)对应的记录绑定,因此无法得到正确结果。
内容的提问来源于stack exchange,提问作者Lalat Putih
相关产品推荐
相关产品推荐

