2009-08-22 7 views
5

मैं एक साधारण प्रयुक्त सबमिट किए गए फ़ील्ड का उपयोग करके MySQL में रिकॉर्ड लाने की कोशिश कर रहा हूं। अधिक सटीक रूप से, उपयोगकर्ता एक नाम (प्रथम नाम या अंतिम नाम या पूर्ण नाम) इनपुट करता है और सर्वर मिलान पंक्तियों को वापस करना चाहिए।MySQL में हैविंग और WHERE क्लॉज के बीच 'OR' का उपयोग करना?

क्या मैं अब तक कर रहा हूँ की तरह कुछ है:

SELECT * FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' 

कि अब के लिए अच्छी तरह से काम, लेकिन वह (जाहिर है) जब कोई उपयोगकर्ता पूरा नाम प्रस्तुत काम नहीं करेगा। क्या पूरी तरह से 'कहां प्रकार की स्थितियों' और 'हैविंग प्रकार की स्थितियों' के बीच एक या एक जोड़ने का कोई तरीका है? इस तरह से मैं कुछ ऐसा कर सकता है:

SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' OR 
    HAVING fullname LIKE '%user_submitted_data%' 

मैं जानता हूँ कि मैं सिर्फ मूल स्ट्रिंग विभाजित सकता है, लेकिन है कि कुछ नकारात्मक प्रभाव पड़ता है आप इस तरह के 'डी Gaule' और इस तरह सामान के रूप में रिक्त स्थान युक्त नाम से निपटने के लिए के बाद से।

उत्तर

4

एक सबक्वेरी कार्य करें:,

SELECT * FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' 

अब उपयोगकर्ता द्वारा पहली बार इनपुट में प्रवेश करती है:

John 
Smith 
John Smith 

आपका प्रारंभिक नमूना क्वेरी है:

SELECT [some fields] 
FROM 
    SELECT firstname, lastname, CONCAT(firstname, ' ', lastname) as fullname 
    FROM people) AS tmp 
WHERE firstname LIKE '%user_submitted_data%' 
OR lastname LIKE '%user_submitted_data%' 
OR fullname LIKE '%user_submitted_data%' 
+0

धन्यवाद, यह इसे ठीक करता है। – Jimmy

1

के कुछ संभव आदानों पर विचार करें , यह प्रश्न उन सभी लोगों को उठाएगा जिनके पहले नाम में 'जॉन' है; यह उन सभी लोगों को भी चुन देगा जिनके अंतिम नाम में 'जॉन' है (उदाहरण के लिए, डेटाबेस में सभी जॉन्सन)। इसी प्रकार, दूसरा इनपुट उन सभी लोगों को चुन देगा जिनके पहले नाम में 'स्मिथ' है; यह उन सभी लोगों को भी चुन देगा जिनके अंतिम नाम में 'स्मिथ' (उदाहरण के लिए, स्मिथसन और स्मिथर्स) शामिल हैं। अब तक सब ठीक है; यह केस-सेंसिटीविटी के मुद्दों के कारण बिल्कुल सही नहीं है (मैं यहां से केस-सेंसिटीविटी को अनदेखा कर दूंगा, लेकिन आपको शायद इसे अनदेखा नहीं करना चाहिए), लेकिन यह ठीक रहेगा।

तीसरा इनपुट केवल उन लोगों को चुन देगा जिनके पहले नाम में 'जॉन स्मिथ' शामिल है; यह उन लोगों को भी उठाएगा जिनके अंतिम नाम में 'जॉन स्मिथ' शामिल है। हालांकि, यह संभावना है कि बहुत कम लोग हैं जो उन मानदंडों को पूरा करते हैं - जिन लोगों को जॉन स्मिथ कहा जाता है, वे सिर्फ पहले नाम पर जॉन होंगे और अंतिम नाम में स्मिथ होंगे। यह आपके मन में होने की संभावना नहीं है।

यह स्पष्ट नहीं है कि आपके पास तालिका में 'पूर्णनाम' नामक कॉलम है या नहीं। यदि आप करते हैं, तो आप पहले नाम और अंतिम नाम से अलग मिलान के बजाय उस कॉलम के खिलाफ मिलान कर सकते हैं। यदि आप नहीं करते हैं, तो हो सकता है कि आप इस तरह के कॉलम का निर्माण कर सकें और उसके बाद क्वेरी चला सकें।

SELECT * 
    FROM (SELECT firstname || ' ' || lastname AS fullname, ... FROM people) AS t 
WHERE t.fullname LIKE '%user_submitted_data%' 

यह उचित रूप से अच्छी तरह से काम करता है।

हालांकि, यदि आप 'चार्ल्स डी गॉल' (या 'चार्ल्स डी गॉल') या 'माइकल वैन डेन बर्ग' जैसे नामों के बारे में चिंतित हैं), तो कोई मिलान 'चार्ल्स गॉल' या ' माइकल बर्ग ', अकेले माइकल वेंडेनबर्ग चलो। आपको शायद उपयोगकर्ता इनपुट में किसी भी स्पेस वर्ण को '%' प्रतीक के साथ प्रतिस्थापित करने की आवश्यकता होगी। फिर भी, आपको समस्या का सामना करना पड़ता है कि शब्दों को उपयोगकर्ता द्वारा दिए गए अनुक्रम में प्रकट होना चाहिए - जो कोई फर्क नहीं पड़ता है, लेकिन आपको जानबूझकर यह तय करना चाहिए कि इससे कोई फर्क नहीं पड़ता। उदाहरण के लिए, यदि इनपुट 'एडम जॉन स्मिथ' है, तो क्वेरी 'जॉन एडम स्मिथ' नहीं पकड़ पाएगी; अगर इनपुट 'स्मिथ, जॉन' है, तो यह किसी को भी नहीं उठाएगा (सबसे अधिक संभावना है)।

यदि आप इसे प्रबंधित करना चाहते हैं, तो आपको शायद उपयोगकर्ता के इनपुट को टोकननाइज़ करना होगा, और अलग-अलग शब्दों पर खोज करना होगा।किसी शब्द की उप-स्ट्रिंग के बारे में पूछने से सावधान रहें (उदाहरण के लिए, कोई व्यक्ति नाम के रूप में 'डी' के बारे में पूछता है) - इस समय कोई भी प्रश्न यह सुनिश्चित नहीं करता है कि उपयोगकर्ता इनपुट शब्द मूल्यों में पूरे शब्दों से मेल खाते हैं (जॉन बनाम जॉनसन), और एसक्यूएल मानक LIKE ऑपरेटर के साथ ऐसा करने के लिए पर्याप्त असंभव है।

+0

गहराई से चांदनी के लिए धन्यवाद। किसी कारण से, ऐसा लगता है जैसे MySQL मेरे सिस्टम (ओएसएक्स) पर केस-असंवेदनशील है, इसलिए यह अब तक ठीक काम कर रहा है। जहां तक ​​यह शब्द आदेश के साथ जाता है, LIKE ऑपरेटर संदर्भ को बहुत अच्छी तरह फिट करता है। जब मुझे कोई उपयोगकर्ता जॉन एडम स्मिथ खोज रहा है तो मुझे जोह स्मिथ को बाहर आने की आवश्यकता नहीं है (न ही चाहते हैं)। खोज नमूना काफी सीमित है। – Jimmy

0

आप WHERE खंड में एक गणना स्तंभ को संदर्भित कर सकते हैं अगर आप एक सबक्वेरी के उस कॉलम को परिभाषित: खोज आप कर रहे हैं के प्रकार के लिए ईमानदारी से

SELECT p.* 
FROM (
    SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
    FROM people 
) p 
WHERE 
    p.firstname LIKE '%user_submitted_data%' OR 
    p.lastname LIKE '%user_submitted_data%' OR 
    p.fullname LIKE '%user_submitted_data%'; 

लेकिन,, LIKE वाइल्डकार्ड के साथ एक भयानक समाधान है । आप एक FULLTEXT सूचकांक का उपयोग कर के बारे में सोचना चाहिए:

CREATE FULLTEXT INDEX people_names ON people(firstname, lastname); 

SELECT * 
FROM people 
WHERE MATCH(firstname, lastname) AGAINST(?); 

पुनश्च: FULLTEXT अनुक्रमित MyISAM भंडारण इंजन के साथ ही काम करते हैं। एक और समाधान, और भी तेज़, पूर्ण टेक्स्ट इंडेक्सिंग के लिए Sphinx Search का उपयोग करना है।

0

हालांकि एक सबक्वायरी का उपयोग अच्छी तरह से करता है, इसका असर होगा क्योंकि आप किसी भी इंडेक्स को मार नहीं रहे हैं।

तालिका में एक गणना कॉलम (firstname || ' ' || lastname) जोड़ने और इसके लिए एक अनुक्रमणिका जोड़ने के बारे में क्या? निश्चित रूप से यह बहुत तेज होगा।

आप मुझे लगता है कि इस तरह

WHERE firstname || ' ' || lastname LIKE '%user_submitted_data%' 

क्वेरी करने में अभी भी दो OR और एक सबक्वेरी की तुलना में तेजी से काम करना चाहिए नहीं कर सकते हैं।

+0

मुझे नहीं लगता कि MySQL में अनुक्रमित गणना कॉलम करने का कोई तरीका है, या तो मेरे शोध दिखाएं। अगर यह करने योग्य है, तो मुझे इसके बारे में सुनना अच्छा लगेगा। – Jimmy

+0

आप सही हो सकते हैं, मुझे लगता है कि गणना किए गए कॉलम का उपयोग करने का कोई तरीका नहीं है !? – Sklivvz

+0

इस बीच MySQL अनुक्रमित गणना कॉलम का समर्थन करता है। लेकिन यदि स्थिति प्लेसहोल्डर ('%') से शुरू होती है तो जैसी स्थितियां इंडेक्स का उपयोग नहीं कर सकती हैं। –

7

बस सभी शर्तों को HAVING खंड में डाल दें।

SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
FROM people 
HAVING firstname LIKE '%user_submitted_data%' 
OR  lastname LIKE '%user_submitted_data%' 
OR  fullname LIKE '%user_submitted_data%

WHERE खंड पंक्तियों जल्दी त्यागने सकता है, लेकिन जब से तुम उन्हें त्यागने नहीं कर सकते जब तक के बाद आप गणना स्तंभ पर हालत का मूल्यांकन किया गया है, और है कि HAVING जब तक इंतजार करना पड़ता है, तो यह आपको WHERE उपयोग करने के लिए कुछ भी नहीं खरीदता है ।

+0

मेरे लिए काम किया, subqueries का उपयोग करने के बजाय एक और अधिक सुरुचिपूर्ण समाधान की तरह लगता है। धन्यवाद! –

संबंधित मुद्दे