group by分组结果由字段collation直接决定,_ci后缀表示不区分大小写,_cs或_bin则区分;可用show full columns查看collation,临时改用collate更轻量且不破坏索引。

GROUP BY 分组结果直接受字段 collation 控制
MySQL 不会“额外判断”大小写,它只是按字段定义的 collation 规则做字符串比较。比如两个值 'User' 和 'user' 是否被归为一组,完全取决于该字段的 collation 是 _ci(case-insensitive)还是 _cs 或 _bin(case-sensitive)。SHOW FULL COLUMNS FROM table_name LIKE 'col_name'; 能立刻看到当前 Collation 值。
用 LOWER() 强制统一大小写但代价明显
当字段 collation 是 utf8mb4_0900_as_cs 时,GROUP BY col 会把 'A' 和 'a' 当作不同值——此时有人会写 GROUP BY LOWER(col)。这确实能绕过问题,但:
-
LOWER(col)无法使用普通索引,哪怕你建了INDEX(col) - MySQL 8.0+ 才支持函数索引:
CREATE INDEX idx_col_lower ON t (LOWER(col)); - 如果表数据量大、QPS 高,长期依赖
LOWER()会拖慢查询,且掩盖了设计缺陷
COLLATE 在查询中临时指定更轻量
不想改表结构,又希望本次查询忽略大小写,直接在 GROUP BY 子句里加 COLLATE:
SELECT 用户名, COUNT(*) FROM user_activity GROUP BY 用户名 COLLATE utf8mb4_0900_ai_ci;
注意几个关键点:
-
COLLATE必须紧跟列名后,不能写成GROUP BY COLLATE utf8mb4_0900_ai_ci 用户名 - 若字段本身是
BINARY类型或定义时带BINARY前缀,COLLATE会被忽略 - 不同 MySQL 版本支持的
collation名称略有差异,先查SHOW COLLATION LIKE 'utf8mb4%ai%';
NULL 和空字符串 '' 的分组行为常被误读
GROUP BY 对 NULL 的处理是“所有 NULL 归为一组”,但 ''(空字符串)和 NULL 是两个完全不同的值,默认分属不同组。业务上若想合并,必须显式转换:
- 把
NULL和''都转成'unknown':COALESCE(NULLIF(用户名,''),'unknown') - 只把
NULL转成'':COALESCE(用户名,'') - 测试时加一句
SELECT 用户名, COUNT(*) FROM t GROUP BY 用户名;,一眼看出NULL是否单独成行
真正容易被忽略的是:collation 不仅影响大小写,还影响重音、全角半角、甚至中日韩汉字变体(如“张”和“張”)。如果业务涉及多语言或历史数据迁移,光看大小写远远不够——得确认 collation 是否同时满足语义一致性与索引有效性。










