अल्पविराम से अलग स्ट्रिंग में मान ढूँढने वाली MySQL क्वेरी


90

मेरे पास COLORS (varchar(50))मेरी तालिका में एक फ़ील्ड SHIRTSहै जिसमें एक अल्पविराम सीमांकित स्ट्रिंग है जैसे कि 1,2,5,12,15,। उपलब्ध रंगों का प्रतिनिधित्व करने वाला प्रत्येक नंबर।

select * from shirts where colors like '%1%'सभी लाल शर्ट (रंग = 1) प्राप्त करने के लिए क्वेरी चलाते समय , मुझे वे शर्ट भी मिलते हैं जिनका रंग ग्रे (= 12) और नारंगी (= 15) है।

मुझे क्वेरी को फिर से कैसे लिखना चाहिए ताकि केवल रंग 1 का चयन हो और नंबर 1 वाले सभी रंग न हों?


6
आप इसे रेगेक्स के माध्यम से कर सकते हैं, मुझे लगता है, लेकिन बहुत बेहतर उपाय यह होगा कि शर्ट के रंगों को एक अलग टेबल (रंगों) में तोड़ दिया जाए और उन्हें जोड़ने के लिए कलर / शर्ट की आईडी का उपयोग करके एक ज्वाइंट टेबल (शर्ट_ कलर) का उपयोग करें।
सिवायजोज

मैं 6 जवाबों के साथ विश्वास नहीं कर सकता कि उनमें से किसी ने भी MySQL के SET डेटा प्रकार का उल्लेख नहीं किया है ..
कॉलिनम

1
इसे देखें: stackoverflow.com/questions/12559876/…
Alireza

जवाबों:


185

क्लासिक तरीका बाईं और दाईं ओर अल्पविराम जोड़ना होगा:

select * from shirts where CONCAT(',', colors, ',') like '%,1,%'

लेकिन find_in_set भी काम करता है:

select * from shirts where find_in_set('1',colors) <> 0

मैंने find_in_set की कोशिश की, लेकिन यह वही परिणाम लौटाता है, जो मेरे द्वारा दर्ज किए गए रंग मान से कोई फर्क नहीं पड़ता ... कोई सुझाव?
बाइक 7777

@ bikey77: शायद यह समस्या है, प्रलेखन कहता है: यह फ़ंक्शन ठीक से काम नहीं करता है यदि पहले तर्क में अल्पविराम (",") वर्ण होता है।
एंडोमर

मेरा गलत, एक ही डमी मूल्यों के कारण यह एक तार्किक गलती थी। यह बढ़िया काम करता है। धन्यवाद!
बाइक 7777

@Andomar इससे पहले कि मैं आपका जवाब पाता मैं wast से संघर्ष कर रहा था, लेकिन आपका काम एक आकर्षण की तरह है ... बहुत बहुत धन्यवाद ..
PHP Mentor

2
इसका प्रदर्शन प्रभाव है क्योंकि Find_in_set ने सूचकांक का उपयोग नहीं किया है
कामरान शाहिद


23

MySQL के लिए FIND_IN_SET फ़ंक्शन पर एक नज़र डालें ।

SELECT * 
    FROM shirts 
    WHERE FIND_IN_SET('1',colors) > 0

1
खबरदार: सेट में मिल तालिका पर अनुक्रमित का उपयोग नहीं करता है।
edigu

11

यह निश्चित रूप से काम करेगा, और मैंने वास्तव में इसे आजमाया:

lwdba@localhost (DB test) :: DROP TABLE IF EXISTS shirts;
Query OK, 0 rows affected (0.08 sec)

lwdba@localhost (DB test) :: CREATE TABLE shirts
    -> (<BR>
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> ticketnumber INT,
    -> colors VARCHAR(30)
    -> );<BR>
Query OK, 0 rows affected (0.19 sec)

lwdba@localhost (DB test) :: INSERT INTO shirts (ticketnumber,colors) VALUES
    -> (32423,'1,2,5,12,15'),
    -> (32424,'1,5,12,15,30'),
    -> (32425,'2,5,11,15,28'),
    -> (32426,'1,2,7,12,15'),
    -> (32427,'2,4,8,12,15');
Query OK, 5 rows affected (0.06 sec)
Records: 5  Duplicates: 0  Warnings: 0

lwdba@localhost (DB test) :: SELECT * FROM shirts WHERE LOCATE(CONCAT(',', 1 ,','),CONCAT(',',colors,',')) > 0;
+----+--------------+--------------+
| id | ticketnumber | colors       |
+----+--------------+--------------+
|  1 |        32423 | 1,2,5,12,15  |
|  2 |        32424 | 1,5,12,15,30 |
|  4 |        32426 | 1,2,7,12,15  |
+----+--------------+--------------+
3 rows in set (0.00 sec)

कोशिश करो !!!


अरे @rolandomysqldba, मैं आपकी क्वेरी का परीक्षण करता हूं और यह ठीक काम करता है लेकिन मुझे इसमें कुछ बदलाव करने की आवश्यकता है। मान लीजिए कि यदि मैं उन सभी शर्टों को प्राप्त करना चाहता हूं जहां कॉलम में रंग का मूल्य 1,2 है।
अहसान सईद

6

यदि रंगों का सेट कम या ज्यादा निर्धारित है, तो सबसे अधिक कुशल और सबसे पठनीय तरीका यह होगा कि आप अपने ऐप में स्ट्रिंग स्थिरांक का उपयोग करें और फिर अपने प्रश्नों में MySQL के SETप्रकार का उपयोग FIND_IN_SET('red',colors)करें। FIND_IN_SET केSET साथ प्रकार का उपयोग करते समय , MySQL सभी मूल्यों को संग्रहीत करने के लिए एक पूर्णांक का उपयोग करता है और मानों की "and"उपस्थिति की जांच के लिए बाइनरी ऑपरेशन का उपयोग करता है जो अल्पविराम से अलग स्ट्रिंग को स्कैन करने से अधिक कुशल है।

में SET('red','blue','green'), 'red'आंतरिक रूप से संग्रहीत किया जाएगा 1, 'blue'आंतरिक रूप में संग्रहीत किया जाएगा 2और आंतरिक रूप 'green'से संग्रहीत किया जाएगा 4। मूल्य 'red,blue'के रूप में संग्रहीत किया जाएगा 3( 1|2) और 'red,green'के रूप में 5( 1|4)।


3

यदि आप MySQL का उपयोग कर रहे हैं, तो एक विधि REGEXP है जिसे आप उपयोग कर सकते हैं ...

http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp

तो आप उपयोग करेंगे:

SELECT * FROM `shirts` WHERE `colors` REGEXP '\b1\b'

यह पता नहीं लगा सका, हालांकि मुझे पूरा यकीन है कि यह मेरी गलती है। धन्यवाद एक सैन्य साथी।
बाइक 7777

3

आपको वास्तव में अपने डेटाबेस स्कीमा को ठीक करना चाहिए ताकि आपके पास तीन टेबल हों:

shirt: shirt_id, shirt_name
color: color_id, color_name
shirtcolor: shirt_id, color_id

फिर यदि आप उन सभी शर्ट्स को ढूंढना चाहते हैं जो लाल हैं, तो आप एक क्वेरी करेंगे जैसे:

SELECT *
FROM shirt, color
WHERE color.color_name = 'red'
  AND shirt.shirt_id = shirtcolor.shirt_id
  AND color.color_id = shirtcolor.color_id

8
@ बेलिंडी: यह केवल सच है अगर आप मानते हैं कि ओपी ने डेटाबेस स्कीमा पर अधिकार संपादित किए हैं; डेटाबेस को फिर से डिज़ाइन करने, डेटा माइग्रेट करने और सभी क्लाइंट को रिफैक्टर करने का समय है; और यह कि इस क्वेरी के लिए जटिलता की कमी बाकी के आवेदन में जटिलता में वृद्धि को रेखांकित करती है।
एंडोमर

1
@Andomar, फिर जब वह पंक्ति पुनः प्राप्ति के लिए आकार प्रतिबंधों में चलेगा और उसका "रिकॉर्ड" क्लिप हो जाएगा, तो असली मज़ा कब शुरू होगा!
ब्लाइंडी

3
@ ब्लिंडी: आप इस बिंदु को याद कर रहे हैं; मैं यह तर्क नहीं दे रहा हूं कि उसके पास सबसे अच्छा समाधान है, बस यह नहीं कि हर किसी को अपने पर्यावरण को अपनी पसंद के अनुसार फिर से डिज़ाइन करने की स्वतंत्रता नहीं है
एंडोमर

मैं @Andomar से सहमत हूँ
एडम बी


0

1. MySQL के लिए:

SELECT FIND_IN_SET(5, columnname) AS result 
FROM table

2. के लिए पोस्ट SQL

SELECT * 
FROM TABLENAME f
WHERE 'searchvalue' = ANY (string_to_array(COLUMNNAME, ','))

उदाहरण

select * 
from customer f
where '11' = ANY (string_to_array(customerids, ','))

0

आप निम्न फ़ंक्शन द्वारा इसे प्राप्त कर सकते हैं।

फ़ंक्शन बनाने के लिए निम्नलिखित क्वेरी चलाएँ।

DELIMITER ||
CREATE FUNCTION `TOTAL_OCCURANCE`(`commastring` TEXT, `findme`     VARCHAR(255)) RETURNS int(11)
NO SQL
-- SANI: First param is for comma separated string and 2nd for string to find.
return ROUND (   
    (
        LENGTH(commastring)
        - LENGTH( REPLACE ( commastring, findme, "") ) 
    ) / LENGTH(findme)        
);

और इस फ़ंक्शन को इस तरह से कॉल करें

msyql> select TOTAL_OCCURANCE('A,B,C,A,D,X,B,AB', 'A');

-7

सभी उत्तर वास्तव में सही नहीं हैं, यह कोशिश करें:

select * from shirts where 1 IN (colors);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.