mysql中in函數和find_in_set函數的區別詳解

前段時間項目中使用到Mysql的FIND_IN_SET函數,感覺挺好用的。過一段時間,老大找到我說,這個需要改爲IN,哈哈,只能改了,原因會在下面分析到!

mysql> select * from test;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | name1,nam2  |
|  2 | name1       |
|  3 | name3       |
|  4 | name2,name4 |
|  5 | name3,name5 |
+----+-------------+
5 rows in set (0.00 sec)

現在我們就需要從這些數據中查詢出 name 字段中包含有name1的數據。
我們先使用 in 來查詢一下:

mysql> select * from test where name in ('name1');
+----+-------+
| id | name  |
+----+-------+
|  2 | name1 |
+----+-------+
1 row in set (0.00 sec)

可以看到只查詢出了一條數據,顯然不是我們想要的結果。
使用 find_in_set:

mysql> select * from test where find_in_set('name1',name);
	+----+------------+
	| id | name       |
	+----+------------+
	|  1 | name1,nam2 |
	|  2 | name1      |
	+----+------------+
	2 rows in set (0.02 sec)

結果是正確的,是我們想要的。
下面解釋下find_in_set 函數:

find_in_set(str1,str2) 函數:返回str2中str1所在的位置索引,其中str2必須以","分割開。
參考mysql文檔中的解釋:

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
FIND_IN_SET(str,strlist)
Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string list is a string composed of substrings separated by “,” characters. If the first argument is a constant string and the second is a column of type SET, the FIND_IN_SET() function is optimized to use bit arithmetic. Returns 0 if str is not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL. This function does not work properly if the first argument contains a comma (“,”) character.

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2

其中有點需要再次提醒的是:strlist必須以逗號(,)分隔
我們可以來做個試驗,把test表中name字段的鏈接字符“,”改爲"-"

mysql> select * from test;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | name1-nam2  |
|  2 | name1       |
|  3 | name3       |
|  4 | name2-name4 |
|  5 | name3-name5 |
+----+-------------+
5 rows in set (0.00 sec)

再次使用find_in_set查詢name字段中包含有name1的數據

mysql> select * from test where find_in_set('name1',name);
+----+-------+
| id | name  |
+----+-------+
|  2 | name1 |
+----+-------+
1 row in set (0.00 sec)

可以看到結果只有一條了。

mysql中FIND_IN_SET函數用來比較是不是包含,不管‘list’字段是變量或給定的字符串常量都能很好的工作。MySQL中原型爲:FIND_IN_SET(str,strlist)。 假如字符串str 在由N 子鏈組成的字符串列表strlist 中,則返回值的範圍在 1 到 N 之間。

一個字符串列表就是一個由一些被‘,‘符號分開的子鏈組成的字符串。如果第一個參數是一個常數字符串,而第二個是type SET列,則 FIND_IN_SET() 函數被優化,使用比特計算。 如果str不在strlist 或strlist 爲空字符串,則返回值爲 0 。如任意一個參數爲NULL,則返回值爲 NULL。這個函數在第一個參數包含一個逗號(‘,’)時將無法正常運行。str也可以是變量,比如表中的一個字段。

當然,這不是我們項目中需要將FIND_IN_SET替換爲IN的原因,因爲在我們項目中兩者都可以實現功能。只是IN比FIND_IN_SET性能高。我們要查詢的字段是主鍵,使用IN時會使用索引,只會查詢表中部分數據。FIND_IN_SET則會查詢表中全部數據,由於數據量比較大,性能肯定不高,所以替換爲IN。想看查詢部分還是全部,可以使用EXPLAIN即解釋功能查看,如果是部分則type爲range(範圍),全部則type爲ALL(全部),還有個type是const,常量級的,呵呵。。。

最佳實踐:

1、如果待查詢的條件是常量那就使用IN,是變量則使用FIND_IN_SET,可以使用索引的,貌似,哈哈。

2、如果使用IN和FIND_IN_SET都能滿足條件,則最好使用IN,理由同上,特別是查詢字段爲主鍵時或有索引時。

3、如果使用IN不能滿足功能需求,那隻能使用FIND_IN_SET了,哈哈,有時候說不定IN中條件加個%號也可以解決問題,加個%號IN就不只是比較是否相等了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章