不会。SQL标准中NULL不等于NULL,但主流数据库将所有NULL归为一组;空字符串''是确定值,与NULL默认分属不同组,需用COALESCE(col, '')等显式合并。

GROUP BY 对字符串字段分组计数,核心不是“能不能”,而是“分得对不对”——空值、大小写、长字段、隐式类型转换都可能让结果悄悄出错。
字符串分组时 NULL 和 '' 会被合并成一组吗?
不会。SQL 标准规定 NULL = NULL 为未知(UNKNOWN),但几乎所有主流数据库(MySQL、PostgreSQL、SQL Server、Oracle)在 GROUP BY 中会把所有 NULL 归为同一组;而空字符串 '' 是确定值,和 NULL 默认分属不同组。
- 想确认当前行为?执行
SELECT col, COUNT(*) FROM t GROUP BY col;,看NULL是否单独占一行 - 若业务上认为
NULL和''都代表“未填写”,必须显式统一:GROUP BY COALESCE(col, '')或GROUP BY CASE WHEN col IS NULL THEN '' ELSE col END - 别依赖数据库“自动合并”,尤其跨库迁移时,PostgreSQL 的
ansi模式可能更严格
大小写敏感导致分组结果不一致怎么办?
完全取决于字段的 collation。例如 MySQL 中 utf8mb4_0900_ai_ci 不区分大小写,utf8mb4_0900_as_cs 区分;PostgreSQL 默认按 LC_COLLATE 处理,通常大小写敏感。
- 查当前排序规则:
SHOW FULL COLUMNS FROM table_name LIKE 'col_name';(MySQL)或\d table_name(PostgreSQL) - 临时强制区分大小写分组:
GROUP BY BINARY tag(MySQL)、GROUP BY tag COLLATE "C"(PostgreSQL) - 避免用
GROUP BY LOWER(tag)——除非你已为LOWER(tag)建了函数索引,否则无法走索引,大数据量下极慢
COUNT(*) 和 COUNT(col) 在字符串分组中为什么差很多?
因为 COUNT(*) 统计每组总行数(含 NULL 行),而 COUNT(col) 只统计该列非 NULL 的行数——哪怕 col 是 VARCHAR 类型,这条规则也不变。
- 常见误判:用
COUNT(name)想统计“有名字的用户”,结果比预期少 → 实际是name字段存了大量NULL或'' - 若需排除空字符串和
NULL:COUNT(NULLIF(name, ''))(MySQL 8.0+/PostgreSQL),或更兼容的写法:SUM(CASE WHEN name != '' AND name IS NOT NULL THEN 1 ELSE 0 END) -
COUNT(DISTINCT col)同样忽略NULL,这点和COUNT(col)一致
对超长字符串(如 TEXT 或 500+ 字符 VARCHAR)直接 GROUP BY 很慢,怎么破?
数据库对长字符串做哈希或排序开销极大,尤其无索引时,可能触发磁盘临时表甚至 OOM。
- 优先考虑是否真需要按完整字符串分组?多数场景只需前缀辨识,比如标签、URL 域名等:
GROUP BY SUBSTRING(tag, 1, 64) - 更稳健方案:加一列
tag_hash CHAR(32),用MD5(tag)或SHA2(tag, 256)预计算并建索引,然后GROUP BY tag_hash - MySQL 8.0+ / PostgreSQL 支持函数索引,可建:
CREATE INDEX idx_tag_lower ON t ((LOWER(tag)));,再配合GROUP BY LOWER(tag)
NULL 被当成有效值、大小写被意外折叠、或者某天数据变长后查询突然卡死——这些点没法靠“跑通就行”发现,得在写第一行 GROUP BY 之前就想清楚。

















