本质是COLLATE不一致导致视觉相同的中文被误判为不同值分组,根源在于全角空格、零宽字符、简繁异体等在弱排序规则下无法语义归一;需统一字段定义、列级COLLATE及collation_connection三者,并优先选用utf8mb4_unicode_ci。

字符编码导致的重复组,本质是 COLLATE 不一致让「看起来一样」的中文被当成不同值分组——不是数据错了,而是比较逻辑被悄悄改写了。
查清字段和连接层的 COLLATE 是否一致
GROUP BY、GROUP_CONCAT、JOIN 都按字段的 COLLATE 做字符串比较。一旦混用,比如 dept_name 在表 A 是 utf8mb4_unicode_ci,在表 B 是 utf8mb4_general_ci,MySQL 可能静默降级比较精度,把「张三」和「张叁」分到不同组。
- 查字段实际 COLLATE:
SELECT COLUMN_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'your_table'; - 查当前连接生效的 COLLATE:
SELECT @@collation_connection; - 三者必须对齐:字段定义 COLLATE、列级 COLLATE、
collation_connection——少一个就可能出问题
GROUP BY 中文字段出现重复分组
现象是 SELECT dept_name, COUNT(*) FROM staff GROUP BY dept_name 返回 12 行,但人工数只有 10 个部门。根源常是全角空格、零宽字符、简繁异体等,在弱 COLLATE 下无法归一。
- 临时验证:加
COLLATE utf8mb4_unicode_ci强制统一,例如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或 MySQL 8.0.30+ 的utf8mb4_zh_0900_as_cs
GROUP_CONCAT 拼出乱码或内容截断
乱码和截断触发条件完全不同:乱码是字符集在拼接环节被错误转码,截断是长度限制硬卡住。
- 乱码必查三项 session 变量:
character_set_client、character_set_connection、character_set_results——任一不是utf8mb4,GROUP_CONCAT就会拿latin1解utf8mb4字节,输出就是æŸäºº - 别用
CONVERT(GROUP_CONCAT() USING utf8mb4)补救:转换发生在拼接之后,损坏已发生 - 截断看
group_concat_max_len:默认 1024 字节,可设为更大值,如SET SESSION group_concat_max_len = 1000000;
真正难处理的不是乱码或截断,而是那些“看起来没毛病”的分组漂移——比如两个字段 COLLATE 对齐了,但 collation_connection 被客户端驱动悄悄覆盖,或者视图里用了 GROUP BY 却没显式指定 COLLATE,这种问题在线上很难复现,也最容易被忽略。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/xinjizixun/109947.html