Mysql的find_in_set函数查询与like查询

对于mysql的like查询,我想都会很熟悉,对于一些基本查询也会常用,但始终不是对大数据量查询的方案。在查询数据需要对某一个字段里的值当作条件时,一般会用到like、instr()、find_in_set(),首先看一下手册里对这3种用法的定义。

expr LIKE pat [ESCAPE ‘escape-char’]

模式匹配,使用SQL简单正规表达式比较。返回1 (TRUE) 或 0 (FALSE)。 若 expr 或 pat 中任何一个为 NULL,则结果为 NULL。
模式不需要为文字字符串。例如,可以被指定为一个字符串表达式或表列。
在模式中可以同LIKE一起使用以下两种通配符:
字符 说明
% 匹配任何数目的字符,甚至包括零字符
_ 只能匹配一种字符

FIND_IN_SET(str,strlist)

假如字符串str 在由N 子链组成的字符串列表strlist 中, 则返回值的范围在 1 到 N 之间 。一个字符串列表就是一个由一些被‘,’符号分开的自链组成的字符串。如果第一个参数是一个常数字符串,而第二个是type SET列,则 FIND_IN_SET() 函数被优化,使用比特计算。如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。 这个函数在第一个参数包含一个逗号(‘,’)时将无法正常运行。

INSTR(str,substr)

返回字符串 str 中子字符串的第一个出现位置。这和LOCATE()的双参数形式相同,除非参数的顺序被颠倒。

然后来实际操作一次,有以下一下这样的一个数据。

data:

+------+----------------+
| id   | tagsid         |
+------+----------------+
|    4 | 2863,4351,4353 |
|    3 |                |
|    5 | 3395,2219      |
|    6 |                |
|    8 |                |
|    9 |                |
|   10 | 2689,4349,2863 |
| 1652 |                |
|   12 | 4347,3161,3029 |
|   13 | 2193,2519,2229 |
+------+----------------+
10 rows in set (0.00 sec)

首先我们使用like查询,结果如下:

mysql> select id,tagsid from tbl_news where find_in_set('2863',`tagsid`) limit 1
0;
+-----+--------------------------+
| id  | tagsid                   |
+-----+--------------------------+
|   4 | 2863,4351,4353           |
|  10 | 2689,4349,2863           |
|  78 | 2863,2197,4327           |
| 245 | 3395,2863                |
|  85 | 2863,2497,3869,4315      |
| 108 | 2193,4301,2863,4303      |
| 121 | 4277,2863,4279,3311,3215 |
| 122 | 4277,4279,2863,4189,3109 |
| 137 | 3361,3811,2829,3255,2863 |
| 149 | 2289,2197,2863,2519,4199 |
+-----+--------------------------+
10 rows in set (0.00 sec)

注意:
select id,tagsid from tbl_news where find_in_set(字段,值) limit 10;
使用find_in_set函数一次返回多条记录

mysql> select id,tagsid from tbl_news where find_in_set(`id`,'78,10,21,2,3,22') limit 10;

id 是一个表的字段 然后每条记录分别是id等于78,10,21,2,3,22的时候,有点类似in (集合)。

mysql> select id,tagsid from tbl_news where `id` in(78,10,21,2,3,22) limit 10;

然后用find_in_set()查询,结果如下:

mysql> select id,tagsid from `tbl_news` limit 10;
+------+----------------+
| id   | tagsid         |
+------+----------------+
|    4 | 2863,4351,4353 |
|    3 |                |
|    5 | 3395,2219      |
|    6 |                |
|    8 |                |
|    9 |                |
|   10 | 2689,4349,2863 |
| 1652 |                |
|   12 | 4347,3161,3029 |
|   13 | 2193,2519,2229 |
+------+----------------+
10 rows in set (0.00 sec)

最后使用instr()查询,结果如下:

mysql> select id,tagsid from tbl_news where instr(`tagsid`,'2863') > 0 limit 10;

+-----+--------------------------+
| id  | tagsid                   |
+-----+--------------------------+
|   4 | 2863,4351,4353           |
|  10 | 2689,4349,2863           |
|  78 | 2863,2197,4327           |
| 245 | 3395,2863                |
|  85 | 2863,2497,3869,4315      |
| 108 | 2193,4301,2863,4303      |
| 121 | 4277,2863,4279,3311,3215 |
| 122 | 4277,4279,2863,4189,3109 |
| 137 | 3361,3811,2829,3255,2863 |
| 149 | 2289,2197,2863,2519,4199 |
+-----+--------------------------+
10 rows in set (0.00 sec)

初步查看并没有什么区别,紧紧在使用方法有所不同,由于查询量比较小,也未做压力测试,查询效率也就不曾而知了,但对于用法上,可根据自己的需求,选择性使用。对于大数据的查询,建议还是数据层上面搭建一个缓冲层,避免对数据库的实时查询等操作,比如索引,缓存,等等措施,毕竟全文查询对mysql压力实在是太大,以上均为本人拙见。