MySQL技术问询:获取每个用户最新事件的完整行记录
获取每个用户最新任务的完整行数据(MySQL)
我太懂这种烦恼了!用GROUP BY确实只能拿到用户和对应的最新时间,没法直接带出完整的行数据——毕竟MySQL不允许在GROUP BY里直接引用非分组、非聚合的字段(除非改宽松模式配置,但那不是规范的解法)。给你几个靠谱的解决方案,覆盖不同MySQL版本:
方法1:关联子查询(兼容所有MySQL版本)
先通过子查询拿到每个用户的最新时间,再关联回原表匹配对应的完整行:
SELECT t.id, t.user, t.time, t.data FROM tasks t INNER JOIN ( -- 先获取每个用户的最新时间 SELECT user, MAX(time) AS max_time FROM tasks GROUP BY user ) tm ON t.user = tm.user AND t.time = tm.max_time;
注意:如果同一个用户有多条记录时间相同且都是最新,这个查询会返回所有这些行。如果要只保留其中一行(比如最新插入的,靠自增id判断),可以把子查询改成
SELECT user, MAX(id) AS max_id FROM tasks GROUP BY user,然后关联id = max_id。
方法2:窗口函数(MySQL 8.0+ 推荐使用)
MySQL 8.0及以上支持窗口函数,用ROW_NUMBER()可以直接给每个用户的记录按时间倒序排号,取排号为1的行即可:
SELECT id, user, time, data FROM ( SELECT id, user, time, data, -- 按用户分组,时间倒序、id倒序排号,确保同一时间取最新插入的行 ROW_NUMBER() OVER(PARTITION BY user ORDER BY time DESC, id DESC) AS rn FROM tasks ) t WHERE rn = 1;
这个方法最清晰,也能灵活处理同一用户多条最新记录的情况,优先推荐给用新版本MySQL的朋友。
方法3:变量模拟窗口函数(MySQL 5.x 适用)
如果还在使用MySQL 5.x(没有窗口函数),可以用用户变量来实现类似的分组排序效果:
SELECT id, user, time, data FROM ( SELECT id, user, time, data, -- 当用户和上一行相同时,行号+1;否则重置为1 @rn := IF(@prev_user = user, @rn + 1, 1) AS rn, @prev_user := user FROM tasks, (SELECT @prev_user := '', @rn := 0) vars -- 先按用户分组,再按时间、id倒序排序 ORDER BY user, time DESC, id DESC ) t WHERE rn = 1;
测试验证
用你提供的测试数据运行以上任意一种方法,都能得到预期输出:
+----+-------+------------+--------------+ | id | user | time | data | +----+-------+------------+--------------+ | 2 | Kalle | 2020-01-01 | latest shit | | 3 | Pelle | 1970-01-01 | regular data | +----+-------+------------+--------------+
内容的提问来源于stack exchange,提问作者user3504575
相关产品推荐
相关产品推荐

