Mysql中in和find_in_set的使用说明

在使用in函数的时候,发现查询的数据少了两条,查过资料才找到原因,跟大家分享一下!


原来以为mysql可以进行这样的查询


1】t_bdp_indices_user_info的表结构:
indices_user_id| create_time|update_time|report_kind
report_kind里面的数据形式:
eg:1,2,3/2,3/3,1/1,2,3,4,5,6/

2】错误:表里面目前有的数据:
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1,2,3       |
|           15948 | 2015-06-30 10:44:01 | NULL                | 2,3         |
|           15949 | 2015-06-30 10:56:37 | NULL                | 2,4         |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2,1         |
+-----------------+---------------------+---------------------+-------------+

3】错误:第一种查询SQL和结果:
 select * from t_bdp_indices_user_info where 1 in (report_kind)
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1,2,3       |
+-----------------+---------------------+---------------------+-------------+
很明显上面的结果集不是我们想要的!
实际上这样是不行的,这样只有当'daodao'是list中的第一个元素(我测试的时候貌似是第一个也是不行的,只有当list字段的值等于daodao时才是对的)时,
查询才有效,否则都的不到结果,即使'daodao'真的再list中,也查不出来!

4】错误:下面的结果仍然不是我们想要的!
select * from t_bdp_indices_user_info where '1' in (report_kind);
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
+-----------------+---------------------+---------------------+-------------+

5】正确:
select * from t_bdp_indices_user_info where find_in_set(1,report_kind);
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1,2,3       |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2,1         |
+-----------------+---------------------+---------------------+-------------+

6】正确:
select * from t_bdp_indices_user_info where find_in_set('1',report_kind);
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1,2,3       |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2,1         |
+-----------------+---------------------+---------------------+-------------+

【总结】

因为list是变量,所以如果想让SQL正常工作,需要用find_in_set()函数:
select * from t_bdp_indices_user_info where find_in_set('1',report_kind);

所以如果list是常量,则可以直接用IN, 否则要用FIND_IN_SET()函数【这句话有点儿怪!】

函数介绍:
FIND_IN_SET(str,strlist)
1.假如字符串str 在字符串列表strlist中, 则返回值的范围在 1 到 N 之间 【如下面++之间的例子】。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
第一次出现的位置索引:
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
+----------------------------+
| FIND_IN_SET('b','a,b,c,d') |
+----------------------------+
|                          2 |
+----------------------------+

mysql> SELECT FIND_IN_SET('b','a,c,b,d');
+----------------------------+
| FIND_IN_SET('b','a,c,b,d') |
+----------------------------+
|                          3 |
+----------------------------+

mysql> SELECT FIND_IN_SET('b','a,b,c,b,d');
+------------------------------+
| FIND_IN_SET('b','a,b,c,b,d') |
+------------------------------+
|                            2 |
+------------------------------+
mysql> SELECT FIND_IN_SET('b','a,b,b,b');
+----------------------------+
| FIND_IN_SET('b','a,b,b,b') |
+----------------------------+
|                          2 |
+----------------------------+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.如果str不在strlist 或strlist 为空字符串,则返回值为 0 。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mysql> SELECT FIND_IN_SET('E','a,b,b,b');
+----------------------------+
| FIND_IN_SET('E','a,b,b,b') |
+----------------------------+
|                          0 |
+----------------------------+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3.字符串列表strlist就是一个由一些被‘,’符号分的字符串组成,用其他分割是不行的。
4.如果第一个参数是一个常数字符串,而第二个是type SET列,则FIND_IN_SET() 函数被优化,使用比特计算。
5.如任意一个参数为NULL,则返回值为 NULL。 这个函数在第一个参数包含一个逗号(‘,’)时将无法正常运行。 
mysql> select * from t_bdp_indices_user_info where find_in_set(1,2,report_kind);
1582 - Incorrect parameter count in the call to native function 'find_in_set'
mysql> select * from t_bdp_indices_user_info where find_in_set('1,2',report_kind);
Empty set


上面的SQL一个有错误,另外一个的查询结果不对!


【延伸】
1.查询多个字符串!
mysql> select * from t_bdp_indices_user_info where find_in_set(1,report_kind) or find_in_set(2,report_kind);
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1,2,3       |
|           15948 | 2015-06-30 10:44:01 | NULL                | 2,3         |
|           15949 | 2015-06-30 10:56:37 | NULL                | 2,4         |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2,1         |
+-----------------+---------------------+---------------------+-------------+

2.利用FIND_IN_set排序,此时的goods_id里面不能应该是"1,3,2,4,5,6"这种数据!
eg:
$ids = '9,3,45,1,8,2,6';


$sql = "... WHERE goods_id IN('{$ids}') ORDER BY FIND_IN_SET(goods_id, '{$ids}')";

数据库中数据的实际顺序:
mysql> select * from t_bdp_indices_user_info where report_kind in (1,2,3,4,5);
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1           |
|           15948 | 2015-06-30 10:44:01 | NULL                | 4           |
|           15949 | 2015-06-30 10:56:37 | NULL                | 3           |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2           |
|           15954 | 2015-06-30 11:19:16 | NULL                | 5           |
+-----------------+---------------------+---------------------+-------------+

从下面的两个结果集可以看出是按照find_in_set(report_kind,'1,2,3,4,5');里面的第二个参数进行排序的!
mysql> select * from t_bdp_indices_user_info where report_kind in (1,2,3,4,5) order by find_in_set(report_kind,'1,2,3,4,5');
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1           |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2           |
|           15949 | 2015-06-30 10:56:37 | NULL                | 3           |
|           15948 | 2015-06-30 10:44:01 | NULL                | 4           |
|           15954 | 2015-06-30 11:19:16 | NULL                | 5           |
+-----------------+---------------------+---------------------+-------------+

mysql> select * from t_bdp_indices_user_info where report_kind in (1,2,3,4,5) order by find_in_set(report_kind,'5,3,4,2,1');
+-----------------+---------------------+---------------------+-------------+
| indices_user_id | create_time         | update_time         | report_kind |
+-----------------+---------------------+---------------------+-------------+
|           15954 | 2015-06-30 11:19:16 | NULL                | 5           |
|           15949 | 2015-06-30 10:56:37 | NULL                | 3           |
|           15948 | 2015-06-30 10:44:01 | NULL                | 4           |
|           15951 | 2015-06-30 11:06:37 | NULL                | 2           |
|               1 | 2015-07-14 14:14:43 | 2015-07-15 15:00:25 | 1           |
|           15871 | 2015-07-07 14:21:25 | NULL                | 1           |

+-----------------+---------------------+---------------------+-------------+



不足之处希望大家补充!

MySQL 的 FIND_IN_SET 函数用于查找一个字符串是否包含指定的子字符串,它的语法如下: ``` FIND_IN_SET(str, strlist) ``` 其,str 是要查找的子字符串,strlist 是要在其查找的字符串列表,它们都是字符串类型。这个函数会返回一个整数值,表示 str 在 strlist 的位置,如果没有找到,则返回 0。 FIND_IN_SET 函数通常用于将多个选项存储在一个字段,例如在一个用户表存储该用户喜欢的颜色(以逗号分隔),然后使用 FIND_IN_SET 函数查找是否包含指定颜色。 例如,假设有一个用户表 user,其有一个字段 colors 存储了用户喜欢的颜色,它们以逗号分隔,如下所示: ``` +----+---------+------------+ | id | name | colors | +----+---------+------------+ | 1 | Alice | red,green | | 2 | Bob | blue,red | | 3 | Charlie | green | +----+---------+------------+ ``` 现在,我们想要查找所有喜欢红色的用户,可以使用以下 SQL 语句: ``` SELECT * FROM user WHERE FIND_IN_SET('red', colors) > 0; ``` 这个 SQL 语句会返回 id 为 1 和 2 的两条记录,因为它们的 colors 字段包含了红色这个选项。 总的来说,FIND_IN_SET 函数适用于需要在一个字段存储多个选项的场景,并且需要进行筛选和查询。但是,如果需要在一个字段存储大量的选项,或者需要对选项进行排序和统计等操作,则不建议使用 FIND_IN_SET 函数,而是应该使用关系型数据库的更加规范化的数据结构来存储选项,例如使用多个表或者使用 JSON 数据类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值