Mysql 正则获取字段的交集

系统 1318 0

问题描述 

比如table1中有两条记录 
name no 
a    2,9 
b    8,10 

然后有一串字符串,是0,1,2,3,4 

然后通过一条sql,找出no为2,9的记录来``` 

因为字符串中有2,数据中也有2 

详细解释 
------------------------------ 
表的字段就是 
name  no     
a     2,9    
b     8,10   
字符串是str="0,1,2,3,4" 
接下来就是查 no字段里跟str里有交集的记录 
查询的结果就是name=a的,no=2,9的 
------------------------------ 

答案是: 

Sql代码   收藏代码
  1. select *  from table1  where concat( ',', no, ',') regexp concat( ',0,|,1,|,2,|,3,|,4,');  



或者: 

Sql代码   收藏代码
  1. select *  from table1  where concat( ',', no, ',') regexp concat( ',(', replace( '0,1,2,3,4', ',', '|'), '),');  



下面是扩展学习: 

由于某些原因,有时候我们没有按照范式的设计准则而把一些属性放到同一个字符串字段中。比如个人兴趣,有时候我们设计表为 
create table members (uid int primary key,uname varchar(20),hobby varchar(100)); 


表中内容如下 

mysql> select * from members; 
+-----+-------+---------------------------------+ 
| uid | uname | hobby                           | 
+-----+-------+---------------------------------+ 
|   1 | AAAA  | 音乐,电影,网络,篮球,阅读,乒乓球 | 
|   2 | BBBB  | 音乐,阅读,乒乓球,发呆,围棋,参禅 | 
|   3 | CCCC  | 交友,乒乓球                     | 
|   4 | DDDD  | 台球,网络,看书,旅游             | 
|   5 | EEEE  | 音乐,发呆,下围棋,参禅           | 
+-----+-------+---------------------------------+ 
4 rows in set (0.00 sec) 

如果我们现在想查找一个与某个用户X (阅读,交友,围棋,足球,滑雪)有着相同爱好的会员记录 如果来操作呢? 

在其它数据库中,我们能只通过程序来或者存储过程来分解这个 "阅读,交友,围棋,足球,滑雪" 字符串为单独的爱好项目,然后一个一个进行 like '%xxxx%' 来查询。 但在MySQL中我们可以直接利用这个regexp正规表达式 来构造SQL语句来实现。 

首先我们把 '阅读,交友,围棋,足球,滑雪' 转换成为正则式 为 '阅读|交友|围棋|足球|滑雪' ,  | 在正则表达式中为 '或' 的意思 

mysql> select replace('阅读,交友,围棋,足球,滑雪',',','|'); 
+---------------------------------------------+ 
| replace('阅读,交友,围棋,足球,滑雪',',','|') | 
+---------------------------------------------+ 
| 阅读|交友|围棋|足球|滑雪                    | 
+---------------------------------------------+ 
1 row in set (0.00 sec) 

这样我们可以用SQL语句如下。 
mysql> select * from members where hobby regexp replace('阅读,交友,围棋,足球,滑雪',',','|'); 
+-----+-------+---------------------------------+ 
| uid | uname | hobby                           | 
+-----+-------+---------------------------------+ 
|   1 | AAAA  | 音乐,电影,网络,篮球,阅读,乒乓球 | 
|   2 | BBBB  | 音乐,阅读,乒乓球,发呆,围棋,参禅 | 
|   3 | CCCC  | 交友,乒乓球                     | 
|   5 | EEEE  | 音乐,发呆,下围棋,参禅           | 
+-----+-------+---------------------------------+ 
3 rows in set (0.00 sec) 


如上语句我们可以通过一句SQL得到所有hobby包含 '阅读,交友,围棋,足球,滑雪' 任一项的记录。 

但上述的语句中还有一点小的缺陷,那就是把 '下围棋' 这一条也选择了出来,如果精确匹配的话这条记录不应该被选中。为了避免这种情况,我们对SQL语句做如下改进。 


把正则式改为 ',(阅读|交友|围棋|足球|滑雪),'  也就是要求匹配项前后必须有一个界定符"," 

mysql> select concat(',(',replace('阅读,交友,围棋,足球,滑雪',',','|'),'),'); 
+---------------------------------------------------------------+ 
| concat(',(',replace('阅读,交友,围棋,足球,滑雪',',','|'),'),') | 
+---------------------------------------------------------------+ 
| ,(阅读|交友|围棋|足球|滑雪),                                  | 
+---------------------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> select * from members 
    -> where concat(',',hobby,',') regexp 
    ->   concat(',(',replace('阅读,交友,围棋,足球,滑雪',',','|'),'),'); 
+-----+-------+---------------------------------+ 
| uid | uname | hobby                           | 
+-----+-------+---------------------------------+ 
|   1 | AAAA  | 音乐,电影,网络,篮球,阅读,乒乓球 | 
|   2 | BBBB  | 音乐,阅读,乒乓球,发呆,围棋,参禅 | 
|   3 | CCCC  | 交友,乒乓球                     | 
+-----+-------+---------------------------------+ 
3 rows in set (0.00 sec) 

这样避免了第5条记录被选中。 

当然也可以利用这种正则式 ',阅读,|,交友,|,围棋,|,足球,|,滑雪,', 但效率显然不如 ',(阅读|交友|围棋|足球|滑雪),' 这种了。 

Mysql 正则获取字段的交集


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论