应使用子查询+JOIN或ROW_NUMBER()窗口函数获取每组最大ID的完整记录,而非GROUP BY+MAX(id),因后者仅返回ID值且严格模式下报错ERROR 1055。
直接 GROUP BY 无法返回整行数据,只配合 MAX(id) 只能拿到 ID 值,拿不到对应那条记录的其他字段。常见错误是写成 SELECT *, MAX(id) FROM table GROUP BY category —— 这在严格模式下会报错 ERROR 1055,因为非聚合字段没出现在 GROUP BY 中。
稳妥做法是先用子查询找出每组最大 ID,再跟原表做 JOIN:
SELECT t1.* FROM my_table t1INNER JOIN (SELECT category, MAX(id) AS max_id FROM my_table GROUP BY category) t2 ON t1.category = t2.category AND t1.id = t2.max_id;
category 和 id 上有联合索引(如 INDEX(category, id)),否则子查询和 JOIN 都可能慢ORDER BY id DESC LIMIT 1 到子查询里再用 ROW_NUMBER()
ONLY_FULL_GROUP_BY,所以别指望靠 SQL_MODE 关掉来“绕过”错误更直观、可控性更强,尤其当需要“每组最新一条”(按时间戳而非 ID)时,ROW_NUMBER() 是标准解法。
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY id DESC) AS rnFROM my_table) ranked WHERE rn = 1;
PARTITION BY category 对应分组字段,ORDER BY id DESC 决定哪条排第一ORDER BY id DESC 换成 ORDER BY created_at DESC, id DESC 防止并列WHERE 子句里,必须套一层子查询或 CTE有人图省事写成:SELECT * FROM my_table WHERE id IN (SELECT MAX(id) FROM my_table GROUP BY category) —— 看似简洁,实际危险。
category 下碰巧有相同最大 id(比如两组都最大是 100),这条语句会误召回多条记录IN 无法保证“每个 category 只匹配自己组内的最大 id”JOIN 差,特别是数据量大时,MySQL 很难优化这个 IN 子查询MySQL 5.6 或更低版本中,有人利用“隐式 GROUP BY 行为”加 ORDER BY 来“碰运气”取首行,例如:SELECT * FROM my_table ORDER BY id DESC GROUP BY category。
id 最大的那条;实际结果依赖执行计划、存储引擎、甚至数据插入顺序ERROR 3029(除非关掉 sql_mode,但不推荐)真正要稳定取每组最大 ID 对应的完整记录,就老实用 JOIN 或 ROW_NUMBER()。ID 字段是否自增、是否唯一、是否有 NULL 值,都会影响结果——动手前先 SELECT COUNT(*), COUNT(id), COUNT(DISTINCT id) FROM my_table 看一眼数据质量。
Tplink企业版路由器WiFi名称的默认设置介绍(Tplink企业版路由器WiFi名称的默认设置是什么)
Tplink路由器灯常亮无法上网的原因分析(如何解决Tplink路由器灯常亮无法上网的问题)
Tplink千兆企业级路由器自动重启的作用和优势介绍(如何设置Tplink千兆企业级路由器自动重启功能)
一根天线的tplink路由器有哪些(一根天线的Tplink路由器的特点和优势介绍)
tplink路由器外网访问不了nas(Tplink路由器外网访问NAS的原因分析)
Tplink无法搜到路由器的原因分析(如何解决Tplink无法搜到路由器的问题)