必须用CHAR_LENGTH()按字符分组,因LENGTH()返回字节长度(如utf8mb4下“你好”为6),导致中文被错误归入字节组;含中文、emoji的场景须统一使用CHAR_LENGTH(),并配合TRIM()和IS NOT NULL过滤空格与NULL。

MySQL里用CHAR_LENGTH()而不是LENGTH()做中文长度分组
想按“几个字符”分组,必须用CHAR_LENGTH();LENGTH()返回字节长度,在UTF8MB4下‘你好’返回6,但业务上它就是2个字符。用错函数会导致中文被错误拆进6字节、9字节等组,完全失真。
- 所有含中文、emoji、日韩文的库,统一用
CHAR_LENGTH() -
LENGTH()只适合纯ASCII字段(如UUID、路径、英文标签) - 建表时若字段定义为
VARCHAR(255) CHARACTER SET utf8mb4,就别碰LENGTH()做语义分组
分组前必须过滤NULL和清理空格
CHAR_LENGTH(NULL)返回NULL,会单独成一组;CHAR_LENGTH('abc ')返回4(末尾空格计入),而业务上这很可能该算3。不处理这两点,统计结果会明显偏高或出现意外的0/1/4长度组。
- 加
WHERE column IS NOT NULL,排除NULL干扰 - 用
TRIM(column)再套CHAR_LENGTH(),避免空格拉长长度 - 如果空字符串
''也要和NULL合并,写成CHAR_LENGTH(COALESCE(TRIM(column), ''))
PostgreSQL和SQL Server的LENGTH行为差异
PostgreSQL的LENGTH()和MySQL的CHAR_LENGTH()一致,返回字符数,且不自动去空格——这是好事,也是坑:你得自己TRIM(),否则'Alice '和'Bob'长度分别是6和3,排序/分组都错位。
- SQL Server必须用
LEN(),但它隐式截掉末尾空格,LEN('x ')=LEN('x'),导致带空格变体全被合并 - SQL Server若需保留空格语义,改用
DATALLENGTH(col)/2(NVARCHAR)或DATALLENGTH(col)(VARCHAR) - 三者都不支持
LEN()在MySQL里——写了直接报错
GROUP BY LENGTH()后COUNT(*)为什么比预期少
不是函数错了,是COUNT(*)统计的是分组后的行数,而每个分组里可能混着NULL、空字符串、带空格值——它们经过CHAR_LENGTH(TRIM(...))后可能归入同一长度组,但原始数据质量差会让这一组的“真实有效值”比例很低。
- 先执行
SELECT TRIM(name), CHAR_LENGTH(TRIM(name)) FROM users LIMIT 10,肉眼确认清洗效果 - 别在
GROUP BY里嵌套太深,如GROUP BY CHAR_LENGTH(TRIM(REPLACE(name, '\t', ''))),调试困难 - 超千万行表慎用,考虑加生成列:
ALTER TABLE users ADD COLUMN name_len TINYINT AS (CHAR_LENGTH(TRIM(name))) STORED,再给name_len建索引
LENGTH()在所有数据库里都返回“字符数”,以及忽略TRIM()带来的语义变化——空格删掉前后,同一个字段可能从“长度10”变成“长度7”,而这个动作是否合理,得看你的业务到底认不认空格。

















