如何查询每个ID对应的TIMESTAMP最大值所在的整行数据
SQL取每个ID最新时间记录的实现方案
常见实现方法
1. 窗口函数法(兼容性最强,支持所有支持SQL:2003标准的新版数据库)
这是最通用的实现方案,适配MySQL 8.0+、PostgreSQL、Oracle、SQL Server等绝大多数主流数据库:
SELECT ID, EVENT, TIMESTAMP FROM ( SELECT ID, EVENT, TIMESTAMP, -- 按ID分组,组内按时间倒序排列,最新的行编号为1 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY TIMESTAMP DESC) AS row_rank FROM `table` ) tmp WHERE row_rank = 1;
如果同ID存在多条时间完全相同的最新记录,需要全部返回时,把ROW_NUMBER()替换为RANK()即可。
2. GROUP BY关联法
如果你习惯用分组聚合的逻辑,也可以用这种写法:
SELECT t1.ID, t1.EVENT, t1.TIMESTAMP FROM `table` t1 INNER JOIN ( -- 先查询每个ID的最大时间 SELECT ID, MAX(TIMESTAMP) AS latest_ts FROM `table` GROUP BY ID ) t2 ON t1.ID = t2.ID AND t1.TIMESTAMP = t2.latest_ts;
3. 相关子查询法
写法更简洁,适合小数据量的查询场景:
SELECT ID, EVENT, TIMESTAMP FROM `table` t1 WHERE TIMESTAMP = ( SELECT MAX(TIMESTAMP) FROM `table` t2 WHERE t2.ID = t1.ID );
4. 无需子查询的数据库特供语法
不需要使用子查询也可以实现该需求,部分数据库提供了专属语法简化这类操作,比如PostgreSQL的DISTINCT ON语法:
SELECT DISTINCT ON (ID) ID, EVENT, TIMESTAMP FROM `table` ORDER BY ID, TIMESTAMP DESC;
这种写法会直接返回每个ID分组内排序后的第一条记录,完全不需要嵌套子查询。
常见问题解答
是不是必须使用子查询才能实现?
不是必须的,除了上面提到的PostgreSQL专属语法可以不用子查询外,也可以用临时表、数据库专属语法等其他方式实现,子查询只是最通用、兼容性最好的实现方式。
注意:代码中的
table是示例表名,实际使用时请替换为你的业务表名,避免和SQL关键字冲突。
内容的提问来源于stack exchange,提问作者Tobitor
相关产品推荐
相关产品推荐

