2011-01-10 40 views
10

這個問題從MYSQL join results set wiped results during IN() in where clause?分割一個MYSQL串從GROUP_CONCAT成(陣列一樣,表達,列表),該IN()可以理解

如下上因此,問題的短版本。你怎麼又被GROUP_CONCAT返回到一個逗號分隔的表達式列表IN()將當作多個項目的遍歷列表中的字符串?

N.B. MySQL的文檔出現來表示爲「表達式列表」,和有趣上IN()的頁面中使用由IN()「(逗號,分隔,列表)」似乎或多或少在MySQL文檔的唯一的頁面永遠提及表達式列表。所以我不知道,如果用於製作數組或臨時表會在這裏任何使用功能。


的問題爲基礎的例子龍版:從2臺DB這樣的:

SELECT id, name, GROUP_CONCAT(tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id GROUP BY person.id; 
+----+------+----------------------+ 
| id | name | GROUP_CONCAT(tag_id) | 
+----+------+----------------------+ 
| 1 | Bob | 1,2     | 
| 2 | Jill | 2,3     | 
+----+------+----------------------+ 

我怎麼能拒絕這一點,這是它可以使用字符串被視爲邏輯等效(1 = X)和(2 = X)...

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id 
GROUP BY person.id HAVING ((1 IN (GROUP_CONCAT(tag.tag_id))) AND (2 IN (GROUP_CONCAT(tag.tag_id)))); 
Empty set (0.01 sec) 

...弄成其中GROUP_CONCAT結果被視爲一個列表,使得對於鮑勃,這將是等同於:

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 1 
GROUP BY person.id HAVING ((1 IN (1,2)) AND (2 IN (1,2))); 
+------+--------------------------+ 
| name | GROUP_CONCAT(tag.tag_id) | 
+------+--------------------------+ 
| Bob | 1,2      | 
+------+--------------------------+ 
1 row in set (0.00 sec) 

...和吉爾,這將相當於:

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 2 
GROUP BY person.id HAVING ((1 IN (2,3)) AND (2 IN (2,3))); 
Empty set (0.00 sec) 

...所以整體結果將是要求不使用具有COUNT所有上市標籤的獨家搜索條款(DISTINCT ...)?

(注:此邏輯作品,未經AND,適用於字符串的第一個字符如

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id 
    GROUP BY person.id HAVING ((2 IN (GROUP_CONCAT(tag.tag_id)))); 
+------+--------------------------+ 
| name | GROUP_CONCAT(tag.tag_id) | 
+------+--------------------------+ 
| Jill | 2,3      | 
+------+--------------------------+ 
1 row in set (0.00 sec) 
+1

這是好的,但值得注意的是,你不需要做`GROUP_CONCAT()`所有`FIND_IN_SET()`。你可以'SELECT GROUP_CONCAT(tag.tag_id)AS tags_list`然後`HAVING FIND_IN_SET(20,tags_list)` – Treffynnon 2011-03-03 16:12:12

回答

33

而不是使用IN(),將使用FIND_IN_SET()是一個選項太

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

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

這裏的基於在討論的示例中的問題的完整示例,確認由提問者在較早編輯的問題進行了測試:

SELECT name FROM person LEFT JOIN tag ON person.id = tag.person_id GROUP BY person.id 
    HAVING (FIND_IN_SET(1, GROUP_CONCAT(tag.tag_id))) AND (FIND_IN_SET(2, GROUP_CONCAT(tag.tag_id))); 
+------+ 
| name | 
+------+ 
| Bob | 
+------+ 
+0

謝謝!我也需要這個。 – 2012-12-06 03:07:22

4

可以傳遞一個字符串作爲陣列上,使用分離隔板和爆炸它在一個功能,將與結果的工作。

對於一個簡單的例子,如果你有一個字符串數組是這樣的:「一|二|樹|四|五」,並想知道如果兩個數組中,你可以做到這一點的方法:

create function str_in_array(split_index varchar(10), arr_str varchar(200), compares varchar(20)) 
    returns boolean 
    begin 
    declare resp boolean default 0; 
    declare arr_data varchar(20); 

    -- While the string is not empty 
    while(length(arr_str) > 0 ) do 

    -- if the split index is in the string 
    if(locate(split_index, arr_str)) then 

     -- get the last data in the string 
    set arr_data = (select substring_index(arr_str, split_index, -1)); 

    -- remove the last data in the string 
    set arr_str = (select 
     replace(arr_str, 
     concat(split_index, 
      substring_index(arr_str, split_index, -1) 
     ) 
     ,'') 
    ); 
    -- if the split index is not in the string 
    else 
    -- get the unique data in the string 
    set arr_data = arr_str; 
    -- empties the string 
    set arr_str = ''; 
    end if; 

    -- in this trivial example, it returns if a string is in the array 
    if arr_data = compares then 
    set resp = 1; 
    end if; 

end while; 

return resp; 
end 
| 

delimiter ; 

我想創建一套有用的MySQL功能,用這種方法來工作。任何有興趣的請與我聯繫。

更多示例,請訪問http://blog.idealmind.com.br/mysql/how-to-use-string-as-array-in-mysql-and-work-with/