2011-01-10 23 views
10

समझ सकते हैं इस सवाल से MYSQL join results set wiped results during IN() in where clause?स्प्लिट एक (सरणी, जैसे, अभिव्यक्ति, सूची) में group_concat से ने MySQL स्ट्रिंग है जो में()

तो, सवाल का लघु संस्करण पर इस प्रकार है। आप GROUP_CONCAT द्वारा लौटाई गई स्ट्रिंग को अल्पविराम से अलग अभिव्यक्ति सूची में कैसे बदलते हैं, जिसमें IN() लूप को एकाधिक आइटम्स की सूची के रूप में पेश करेगा?

एनबी। 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 = एक्स) और (2 = एक्स) ...

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 ...)?

(ध्यान दें: इस तर्क के बिना काम करता है और, स्ट्रिंग के प्रथम वर्ण के लिए आवेदन जैसे

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

यह अच्छा है, लेकिन यह ध्यान देने योग्य बात है कि आप() 'में सभी' FIND_IN_SET() '' group_concat करने की ज़रूरत नहीं है लायक है। आप बस GROUP_CONCAT (टैग.tag_id) AS टैग_लिस्ट' चुन सकते हैं और फिर 'FIND_IN_SET (20, टैग_सूची)' – Treffynnon

उत्तर

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

है धन्यवाद! मुझे भी इसकी ज़रूरत है। –

+0

बिल्कुल सही! एक युक्ति: यह मत भूलना कि चूंकि यह फ़ंक्शन कॉल की तरह है, इसलिए उद्घाटन ब्रैकेट/कोष्ठक से पहले ** कोई स्थान नहीं होना चाहिए, ** अन्यथा आपको एक त्रुटि मिलेगी 'फ़ंक्शन dbname.FIND_IN_SET मौजूद नहीं है'। – user568458

+0

वैसे यह एक समाधान है, लेकिन मुझे पता चला है कि FIND_IN_SET आईएन की तुलना में बेहद कम कुशल है ... क्या कोई सवाल है कि क्या वास्तव में प्रश्न पूछने का कोई तरीका है, एक स्ट्रिंग को सरणी में विभाजित करने का एक तरीका चर? –

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/