FIND_IN_SET(str,strlist) 是一个 MySQL 库函数(大小写都支持),可以直接在 WHERE 中使用,主要作用就是判断前一个字符串常量是否在后者字符串列表变量中。返回在字符串列表匹配到的索引,索引从 1 开始计数,匹配不到返回 0。

在 sql 语句中,字段名是一个变量存在,而带入的参数就是常量。强调常量和变量是因为函数只接受这样的类型匹配,其他形式会报错或者查询不到结果。在这个函数里如果把字符串常量改成变量,sql 语句执行是查不到东西的(应该是函数内部做了判断),而如果都是常量那么返回结果是固定的——匹配项的索引或者 0。strlist是一个字符串列表,或者更准确的说是一个字符串列表字符串,展现形式 apple,bird,cat,多个字符串用英文逗号隔开(为什么不是中文逗号或者其他符号?因为这是人家做出来的软件,全世界通用)。

主要应用场景:多选分类的字段的单个分类匹配查询。比如一个对象录入分类时可多选,那么一般情况会把分类字段处理成 1,2,3 的形式。然而在展示页面搜索时,单个分类搜索会比较困难。因为分类 ID 通过常规的 like 进行匹配可能会出现错误匹配的情况。比如分类 ID 为 2,那么它会搜索出所有包含 2 的分类字段,1,2,311,12,1321,22,23...都会匹配成功,这显然是不对的。FIND_IN_SET(2, cateids) 就可以很精准并且轻松地解决。

当然,like 也是可以通过一些特别的处理,从而达到精准匹配效果。将存储字段内容首位加上 ,(英文逗号),然后匹配参数处理成 ,2, 的形式。字段可以写入的时候就加上 ,,然后匹配 catids like '%,2,%'。也可以动态加上去,比如 CONCAT(',',catids,',') like '%,2,%'。注意,MySQL 中字符串拼接可不是 + 或者 .,而是 CONCAT() 函数。

多个分类匹配单选分类字段比较简单,可以直接用 IN 解决。如:catid IN (1,2,3)

如果前端应用场景是多个分类匹配多选分类字段呢?这种情况应该怎么处理呢?

当然可以用 FIND_IN_SET,循环遍历的方式把需要的项拼接起来 FIND_IN_SET(2, cateids) AND FIND_IN_SET(3, cateids) AND...

还有另外一种方法,使用 REGXP 语句。REGXP 表示正则匹配,比 like 只能用 _ 表示单个字符 和 % 表示 0 个或多个任意字符更加灵活。

使用例子:

CONCAT(',',catids,',') REGXP ',2,|,3,|,4,'