统计“苹果”出现总次数应使用length差值法:sum((length(name)-length(regexp_replace(name,'苹果','','g')))/length('苹果'));统计含“苹果”的记录数则用count(*) where name like '%苹果%'。

直接用 COUNT() 配合 LIKE 或正则函数就能统计,但必须注意匹配逻辑是否覆盖子串、大小写、边界词等真实需求,否则结果会漏计或多计。
用 LIKE 统计字段中出现某词的记录数(非词频)
这是最常用也最容易误解的场景:很多人想“统计‘苹果’出现多少次”,实际只写了统计“包含‘苹果’的行数”。LIKE 只能判断存在性,无法返回单行内重复次数。
- 正确写法(统计含“苹果”的行数):
SELECT COUNT(*) FROM products WHERE name LIKE '%苹果%';
- 错误理解:若某行
name = '苹果手机 苹果耳机',该行仍只被计为 1 次 - 大小写敏感取决于数据库排序规则(如 MySQL 默认不敏感,PostgreSQL 默认敏感),必要时加
LOWER(name) LIKE '%苹果%'
在 PostgreSQL 中用 regexp_replace() 计算单字段内词频
要真正统计“苹果”在整个表中作为子串出现了多少次(包括一行多次),PostgreSQL 提供了可靠路径:先删掉所有非目标词,再比对长度差。
- 核心思路:
LENGTH(col) - LENGTH(regexp_replace(col, '苹果', '', 'g'))得到总字符删减量,再除以目标词长度 - 完整示例(统计所有记录中“苹果”出现总次数):
SELECT SUM((LENGTH(name) - LENGTH(regexp_replace(name, '苹果', '', 'g'))) / LENGTH('苹果')) AS apple_count FROM products; - 注意:
'g'标志必须加,否则只替换首次匹配;空字符串''不能写成NULL,否则整行结果变NULL - 若需按行展开查看每条记录的词频,把
SUM()去掉,直接选计算表达式即可
MySQL 8.0+ 用 REGEXP_REPLACE() 实现类似统计
MySQL 8.0 起支持 REGEXP_REPLACE(),但行为和 PostgreSQL 有差异:不支持 'g' 标志,且默认只替换第一次。必须用重复调用或变量模拟全局替换,更稳妥的做法是用 JSON 辅助拆解。
- 较实用的替代方案(适用于词较固定、无正则元字符):
SELECT SUM(CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, '苹果', ''))) / CHAR_LENGTH('苹果') AS apple_count FROM products; -
REPLACE()在 MySQL 中天然全局替换,比正则更稳;注意用CHAR_LENGTH()(非LENGTH()),避免多字节字符出错 - 如果词含下划线
_或百分号%,LIKE会误判,但REPLACE()不受影响——这是它比LIKE更适合词频统计的关键原因
真正难的不是写出某个语句,而是确认业务定义:“包含该词的记录数”和“该词在所有记录中出现的总次数”完全是两个指标,选错就全错。另外,中文分词边界(比如“苹果汁”算不算含“苹果”)往往需要应用层预处理,SQL 很难干净解决。











