MySQL实现单词解扰:检索所有字母全包含于输入串的单词
问题核心
需求为:给定输入字符串(比如"Hello"),从词表中匹配所有满足「单词用到的每一个字母,都包含在输入字符串的字符范围内」的词,比如hole、lol、eh、hell都是符合要求的结果,hi、loop这类带输入范围外字母的词需要被过滤掉。
你之前写的LIKE查询存在本质逻辑错误:
SELECT * FROM words WHERE word LIKE (%h%) OR (%e%) OR (%l%) OR (%l%) OR (%o%)
这段语句的匹配规则是「只要单词包含h/e/l/o中任意一个字母就命中」,完全没有限制其他字符的出现,自然会返回带i的hi、带p的loop这类不符合要求的结果,而且语法上LIKE后的匹配字符串也缺少单引号包裹。
实现方法
核心匹配逻辑是:整个单词的所有字符,都必须属于输入字符串拆解出的字符集合;如果要求严格匹配字符数量(比如输入Hello中l只出现2次,不允许匹配含3个l的词),还需要额外校验每个字符的出现次数不超过输入中的计数。
- 基础版:仅校验字符范围(不限制同字符出现次数)
支持正则查询的数据库(MySQL、PostgreSQL等)都可以用正则实现,先把输入字符串去重得到字符集(Hello去重后为h、e、l、o),写正则强制单词从开头到结尾只能由这几个字符构成:
正则规则说明:-- MySQL 写法 SELECT * FROM words WHERE word REGEXP '^[helo]+$';^标记单词起始位置,$标记单词结束位置,确保匹配覆盖整个单词[helo]表示匹配集合内的任意一个字符+表示匹配至少1个字符
这个写法会过滤掉所有带h/e/l/o以外字符的单词。如果是SQLite环境,可以用GLOB语法实现同等效果:
SELECT * FROM words WHERE word GLOB '[helo]*' AND word NOT GLOB '*[^helo]*'; - 严谨版:同时校验字符出现次数上限
如果你需要严格限制同字符的出现次数(比如Hello中h最多1个、e最多1个、l最多2个、o最多1个),可以在正则过滤的基础上,追加字符计数校验,以MySQL为例:
计数逻辑很简单:把单词中指定字符替换为空,替换前后的字符串长度差就是该字符的出现次数,只要次数不超过输入字符串中对应字符的总数量,就符合要求。PostgreSQL、SQLite等其他数据库只需要替换对应的长度、字符串函数名即可复用这套逻辑。SELECT * FROM words WHERE word REGEXP '^[helo]+$' -- 计算每个字符在单词中的出现次数,和输入中的计数对比 AND (LENGTH(word) - LENGTH(REPLACE(word, 'h', ''))) <= 1 AND (LENGTH(word) - LENGTH(REPLACE(word, 'e', ''))) <= 1 AND (LENGTH(word) - LENGTH(REPLACE(word, 'l', ''))) <= 2 AND (LENGTH(word) - LENGTH(REPLACE(word, 'o', ''))) <= 1;
内容的提问来源于stack exchange,提问作者Rakan Selawi
相关产品推荐
相关产品推荐

