如何在MySQL中按分组获取每组最新创建的记录?
需求说明
我有一张结构如下的数据表(假设表名为products):
| product_id | client_id | category | price | created_date |
|---|---|---|---|---|
| 1 | 1 | A | 3.1 | 2022-11-01 |
| 2 | 1 | A | 3.2 | 2022-11-02 |
| 3 | 1 | B | 3.3 | 2022-11-03 |
| 4 | 1 | B | 3.4 | 2022-11-04 |
| 5 | 2 | B | 3.5 | 2022-11-05 |
| 6 | 2 | B | 3.6 | 2022-11-06 |
| 7 | 2 | A | 3.7 | 2022-11-07 |
| 8 | 2 | C | 3.8 | 2022-11-08 |
需要按client_id和category分组,查询每组中created_date最新的记录,期望结果如下:
| product_id | client_id | category | price | created_date |
|---|---|---|---|---|
| 2 | 1 | A | 3.2 | 2022-11-02 |
| 4 | 1 | B | 3.4 | 2022-11-04 |
| 6 | 2 | B | 3.6 | 2022-11-06 |
| 7 | 2 | A | 3.7 | 2022-11-07 |
| 8 | 2 | C | 3.8 | 2022-11-08 |
另外还有一个更贴近实际场景的示例(假设表名为demo_table),期望结果如下:
| val1 | val2 | num1 | num2 | created_date |
|---|---|---|---|---|
| X | A | 33 | 333 | 2022-11-03 |
| X | B | 66 | 666 | 2022-11-06 |
| X | C | 88 | 888 | 2022-11-08 |
| X | D | 99 | 999 | 2022-11-09 |
| Y | A | 111 | 1111 | 2022-11-11 |
MySQL解决方案
方法1:使用窗口函数(MySQL 8.0及以上版本推荐)
利用ROW_NUMBER()窗口函数按分组字段排序后给每条记录编号,取编号为1的即为每组最新记录。
针对products表的查询语句:
SELECT product_id, client_id, category, price, created_date FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY client_id, category ORDER BY created_date DESC) AS rn FROM products ) t WHERE rn = 1;
针对demo_table的查询语句(按val1和val2分组取最新记录):
SELECT val1, val2, num1, num2, created_date FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY val1, val2 ORDER BY created_date DESC) AS rn FROM demo_table ) t WHERE rn = 1;
方法2:子查询关联(兼容MySQL 5.x版本)
先通过子查询获取每组的最大created_date,再关联原表获取完整记录。
针对products表的查询语句:
SELECT p.* FROM products p INNER JOIN ( SELECT client_id, category, MAX(created_date) AS max_date FROM products GROUP BY client_id, category ) t ON p.client_id = t.client_id AND p.category = t.category AND p.created_date = t.max_date;
针对demo_table的查询语句:
SELECT d.* FROM demo_table d INNER JOIN ( SELECT val1, val2, MAX(created_date) AS max_date FROM demo_table GROUP BY val1, val2 ) t ON d.val1 = t.val1 AND d.val2 = t.val2 AND d.created_date = t.max_date;
注意:如果同一分组内存在多条
created_date相同的最新记录,方法1只会返回其中一条(按默认排序),方法2会返回所有符合条件的记录,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者JohnP
相关产品推荐
相关产品推荐

