substring硬切片易出错,需先trim去空格、用locate定位再切;null/空值须case兜底;长度不固定优先用substring_index;where/group by中使用会失效索引,应建生成列索引。

用 SUBSTRING 提取固定位置关键词容易出错
直接对字段硬切片(比如 SUBSTRING(content, 1, 5))只在格式高度统一时才可靠。现实里日志、标题、描述字段往往开头不齐、有空格或前缀,一刀切会截出空值、乱码或半截词。
- 先用
TRIM()去首尾空格,再考虑切片,否则SUBSTRING(TRIM(content), 1, 5)和裸切结果可能差两个字符 - 如果关键词藏在中间(比如“【类型】xxx”),得先用
LOCATE()或POSITION()找起始偏移,再套SUBSTRING(),不能凭感觉写数字 - MySQL 中索引从 1 开始,PostgreSQL/SQL Server 从 1 开始,但某些 ODBC 驱动可能转译异常——查
SELECT SUBSTRING('abc', 1, 1)是否返回'a'是最快验证方式
分组统计前必须处理 NULL 和空字符串
SUBSTRING 遇到 NULL 直接返回 NULL,而 GROUP BY 会把所有 NULL 归为一组,导致“未知关键词”被误计为高频项;空字符串 '' 也会参与分组,和 NULL 不同但同样干扰业务语义。
- 用
CASE WHEN content IS NULL OR TRIM(content) = '' THEN 'N/A' ELSE SUBSTRING(TRIM(content), 1, 8) END统一兜底 - 若关键词长度不固定(如提取域名后缀),优先用
SUBSTRING_INDEX()(MySQL)或SPLIT_PART()(PostgreSQL),比硬切更鲁棒 - 在
GROUP BY子句里必须复用和SELECT中完全一致的表达式,别写SUBSTRING(content, 1, 8)和SUBSTRING(TRIM(content), 1, 8)两套逻辑
性能隐患:SUBSTRING 在 WHERE 或 GROUP BY 中无法走索引
只要 SUBSTRING() 出现在 WHERE 条件或 GROUP BY 表达式里,对应字段的索引基本失效,尤其是大表上会触发全表扫描。
- 高频查询场景下,宁可加一个生成列(MySQL 5.7+ 支持
STORED列)并对其建索引,例如:ALTER TABLE logs ADD keyword_prefix VARCHAR(10) STORED AS (SUBSTRING(TRIM(content), 1, 10)) - 临时分析可以接受慢,但上线 SQL 必须确认执行计划里没出现
Type: ALL或Extra: Using filesort - 如果只是想筛出含某关键词的记录,用
LIKE '%keyword%'或全文索引比切片再匹配更合适
不同数据库的 SUBSTRING 行为差异要手动对齐
MySQL、PostgreSQL、SQL Server 都叫 SUBSTRING,但参数顺序和默认行为不一致——最常踩坑的是第三个参数(长度)是否可省略,以及超出源长时返回什么。
- MySQL:
SUBSTRING(str, pos, len),len可省略,表示取到末尾;超长返回实际剩余部分 - PostgreSQL:
SUBSTRING(str FROM pos FOR len),FOR len必须显式写出,省略则语法错误 - SQL Server:
SUBSTRING(str, start, length),超长返回NULL(不是截断!),这点极易引发统计结果少几行 - 跨库迁移时,务必用
SELECT SUBSTRING('hello world', 7, 100)实测,别信文档速查表
SELECT content, SUBSTRING(TRIM(content), 1, 6) FROM table LIMIT 10,确认每行都切出了合理内容,再加 GROUP BY 和 COUNT(*)。不然分组结果看着整齐,底下全是错的。










