Mysql 正則獲取字段的交集【轉】


問題描述 

比如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條記錄被選中。 

當然也可以利用這種正則式 ',閱讀,|,交友,|,圍棋,|,足球,|,滑雪,', 但效率顯然不如 ',(閱讀|交友|圍棋|足球|滑雪),' 這種了。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM