MySQL 5.7+ GROUP BY 报错主因是启用ONLY_FULL_GROUP_BY模式且SELECT字段未全在GROUP BY中;TEXT/BLOB不可直接分组,需SUBSTRING截取后CAST为CHAR(N)才可,但应优先重构逻辑用业务字段分组。

MySQL 5.7+ 中 GROUP BY 报错 Expression #1 of SELECT list is not in GROUP BY clause
这是 MySQL 严格模式下的典型报错,本质不是 TEXT/BLOB 不能 GROUP BY,而是你 SELECT 的字段没全出现在 GROUP BY 子句里,且启用了 sql_mode=ONLY_FULL_GROUP_BY。TEXT/BLOB 字段本身在 MySQL 中确实**不能直接用于 GROUP BY**(会隐式转为前 1024 字节比较,且 8.0.19+ 已禁止),但真正卡住你的往往是这个模式和字段混用。
常见错误现象:SELECT id, content FROM posts GROUP BY user_id; —— content 是 TEXT 类型,又没出现在 GROUP BY 里,MySQL 直接拒绝执行。
- 先确认是否真被模式拦截:运行
SELECT @@sql_mode;,看是否含ONLY_FULL_GROUP_BY - 临时绕过(仅调试):
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));,但不解决根本问题 - 别试图对
TEXT字段做GROUP BY content—— MySQL 不允许,会报Unsupported type for key或直接截断
把 TEXT 转成可分组的等价类型:用 SUBSTRING + CAST
如果业务上真需要按内容“前缀”分组(比如归类相似描述),必须显式截断并转为定长类型。直接 CAST(content AS CHAR) 不行 —— MySQL 对 TEXT 的 CAST 仍受限;得先截再转。
使用场景:日志摘要去重、用户反馈关键词聚类、短文本内容归档
- 安全长度选
SUBSTRING(content, 1, 255),再CAST(... AS CHAR(255)),避免超长导致隐式转换失败 - 别用
LEFT(content, 255)—— 它在某些版本对 TEXT 返回 BLOB,依然无法 GROUP BY - 示例:
SELECT CAST(SUBSTRING(note, 1, 255) AS CHAR(255)) AS note_prefix, COUNT(*) FROM logs GROUP BY note_prefix; - 性能影响:SUBSTRING + CAST 无法走索引,大数据量时务必加前缀索引:
ALTER TABLE logs ADD KEY idx_note_prefix (note(255));
真正该做的:重构查询逻辑,避开对 TEXT 的 GROUP BY
绝大多数情况下,想对 TEXT 字段 GROUP BY,其实是设计误判。TEXT 应该是“附属描述”,主键或业务标识才是分组依据。强行分组只会带来歧义(比如两条不同 TEXT 内容被 SUBSTRING 截成一样,就合并了)。
常见错误做法:SELECT *, GROUP_CONCAT(title) FROM articles GROUP BY content; —— content 是 TEXT,不可行,且语义混乱
- 正确思路:用主键或唯一业务字段分组,TEXT 仅作聚合展示,例如:
SELECT category, MAX(created_at), COUNT(*) FROM articles GROUP BY category; - 若需关联 TEXT 内容,用子查询或 JOIN 获取最新/最长一条:
(SELECT content FROM articles a2 WHERE a2.category = a1.category ORDER BY id DESC LIMIT 1) - 兼容性注意:PostgreSQL 允许 TEXT GROUP BY,SQLite 也支持,但 MySQL 就是不支持——别指望跨数据库写法统一
升级到 MySQL 8.0 后的额外限制
MySQL 8.0.19+ 彻底禁用了对 TEXT/BLOB 类型的 GROUP BY 和 ORDER BY,哪怕你加了 SUBSTRING 也不行,除非明确 CAST 成非大对象类型。
错误信息会变成:ERROR 3067 (HY000): Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column ... which is not functionally dependent on columns in GROUP BY clause
- 必须显式 CAST:
GROUP BY CAST(SUBSTRING(body, 1, 500) AS CHAR(500)),缺AS CHAR(N)会失败 -
VARCHAR(1000)也不行——它仍是变长类型,MySQL 8.0+ 只认定长CHAR(N)作为安全分组类型 - 如果字段实际长度常超 500,考虑用哈希替代:
GROUP BY SHA2(body, 256),但要注意哈希碰撞风险(极低,但存在)

















