分组汇总失败主因是字符集或排序规则不一致,导致中文被误判为不同值或报错;需统一字段collation与@@collation_connection,并确保character_set_client/connection/results均为utf8mb4。

分组汇总失败不是 GROUP BY 语法错了,而是字符集或排序规则不一致让 MySQL 把本该归为一组的中文判成了“不同值”——比如“技术部”和“技术部”(后者含不可见空格)被分到两组,COUNT 结果虚高;或者直接报 Illegal mix of collations 错误。
查清字段和连接层的 collation 是否对齐
GROUP BY 比较字符串时,用的是字段定义的 collation 和当前会话的 @@collation_connection,两者不一致就会出问题。
- 查字段真实 collation:
SELECT COLUMN_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'your_table' AND COLUMN_NAME = 'dept_name'; - 查连接生效 collation:
SELECT @@collation_connection; - 如果字段是
utf8mb4_unicode_ci,但连接是latin1_swedish_ci,MySQL 会隐式转换字段值再比较,结果不可靠,还可能跳过索引
GROUP BY 中文字段重复分组或漏分组
视觉相同但字节不同的字符串(如全角/半角空格、零宽字符、简繁异体字),在宽松 collation(如 utf8mb4_general_ci)下可能被当成相等,在严格 collation(如 utf8mb4_0900_as_cs)下却被判为不同——分组结果就漂移了。
- 临时验证:在 GROUP BY 子句里显式加 collation,例如
GROUP BY dept_name COLLATE utf8mb4_unicode_ci - 长期解法:建表时就声明
dept_name VARCHAR(50) COLLATE utf8mb4_unicode_ci NOT NULL,避免依赖数据库默认值 - 别用
utf8mb4_general_ci——它已废弃,且对中文归一支持差;新项目优先选utf8mb4_0900_as_cs,老系统保持utf8mb4_unicode_ci更稳妥
子查询或 JOIN 场景下 GROUP BY 失败
跨表聚合时,如果主表字段和子查询返回列的 collation 不同,MySQL 会直接拒绝执行,报 Illegal mix of collations。
- 错误写法:
(SELECT name FROM users)直接用于IN或JOIN,没处理 collation - 正确做法:在子查询 SELECT 列上用
CONVERT(name USING utf8mb4) COLLATE utf8mb4_unicode_ci,不是包整个子查询 - JOIN 时两边字段 collation 必须完全一致——哪怕都是
utf8mb4,utf8mb4_unicode_ci和utf8mb4_0900_ai_ci也不能混用 - 更安全的路:给旧编码字段建 STORED 虚拟列,例如
ADD COLUMN name_utf8mb4 VARCHAR(100) AS (CONVERT(name USING utf8mb4)) STORED,再在这个列上建索引并用于 JOIN
GROUP_CONCAT 拼接后乱码或内容截断
GROUP_CONCAT 的结果乱码,90% 是因为会话级字符集没设对;截断则是 group_concat_max_len 太小,两者常被混淆。
- 必须确认三项 session 变量全为
utf8mb4:character_set_client、character_set_connection、character_set_results—— 用SHOW VARIABLES LIKE 'character_set%';查 - 别信
SET NAMES utf8mb4就够了:它只改前两项,character_set_results不变,GROUP_CONCAT仍可能按 latin1 解码 - 调大长度限制:
SET SESSION group_concat_max_len = 1000000;(单位是字节,utf8mb4 下一个 emoji 占 4 字节) - CAST 比 CONVERT 更稳:
GROUP_CONCAT(CAST(name AS CHAR CHARACTER SET utf8mb4)),确保拼接过程就在正确字符集下运行
字符集问题从来不是单点故障,它是链条式的——表字段、连接初始化、会话变量、函数内部行为,漏掉任意一环,补救语句就只是在错误数据上打转。最易被忽略的是 @@collation_connection 和 character_set_results 这两个变量,它们不显眼,却决定着 GROUP BY 和 GROUP_CONCAT 的底层行为。











