MySQL按currency_id分组获取对应最新timestamp记录的技术问询
解决MySQL按分组取最新记录的问题
哈哈,这种分组拿最新记录的需求真的是MySQL里的经典坑!我刚捡起来用的时候也踩过,太懂这种明明觉得简单却卡壳的感觉了😅
先给你说清楚为啥原来的写法不行:
- 你第一个
GROUP BY currency_id的查询,在MySQL默认配置(关闭ONLY_FULL_GROUP_BY)下,会返回每个分组里的任意一行,并不是你以为的“首行”,这是MySQL的非标准行为——换做PostgreSQL这类数据库直接会报错,因为你SELECT的列既不在GROUP BY里,也没用聚合函数。ORDER BY timestamp DESC只是对分组后的结果整体排序,根本管不到分组内部的行顺序,所以肯定拿不到最新的那条。 - 那个
LIMIT 6的写法完全是碰运气,不仅新增币种要改数字,还没法保证每个币种都能拿到最新记录,绝对不能用在正经业务里。
下面给你两种靠谱的解法,分版本适用:
方法一:用窗口函数(MySQL 8.0+推荐)
这是最简洁直观的写法,MySQL 8.0及以上版本支持窗口函数,直接按分组内部排序取第一条:
SELECT id, price, currency_id, timestamp FROM ( SELECT id, price, currency_id, timestamp, -- 按currency_id分组,每组内按timestamp倒序编号 ROW_NUMBER() OVER (PARTITION BY currency_id ORDER BY timestamp DESC) AS row_num FROM prices ) temp -- 取每组的第一条(也就是timestamp最新的那条) WHERE row_num = 1;
如果同一个currency_id有多个记录的timestamp完全相同,ROW_NUMBER()会给它们编不同的号,只取一条;要是想把这些相同时间的都返回,可以换成RANK()或者DENSE_RANK()。
方法二:子查询关联(兼容MySQL 5.x)
如果你的MySQL版本比较旧,不支持窗口函数,就用子查询先找出每个currency_id的最大timestamp,再和原表关联:
SELECT p.id, p.price, p.currency_id, p.timestamp FROM prices p INNER JOIN ( -- 先拿到每个币种的最新时间戳 SELECT currency_id, MAX(timestamp) AS latest_ts FROM prices GROUP BY currency_id ) latest ON p.currency_id = latest.currency_id AND p.timestamp = latest.latest_ts;
这里要注意:如果同一个币种有多个记录的timestamp等于最大时间,这个查询会返回所有这些记录。如果业务上要求只返回一条(比如取id最大的),可以把关联条件改成p.id = (SELECT MAX(id) FROM prices WHERE currency_id = latest.currency_id AND timestamp = latest.latest_ts),或者在子查询里同时取MAX(id)来关联,具体看你的业务逻辑。
内容的提问来源于stack exchange,提问作者Story Teller
相关产品推荐
相关产品推荐

