2010-03-12 13 views
6

ठीक महत्व देता है यहाँ मेरी समस्या है:वैकल्पिक खोज मापदंडों अशक्त साथ पंक्तियों

इससे पहले कि मैं वर्णन शुरू करते हैं, मैं आपको बता दूँ कि मैं एक बहुत googled है और मैं एक के लिए इस प्रश्न पोस्ट कर रहा हूँ चलो अच्छा इष्टतम समाधान :)

मैं USERPROFILES ... उपयोगकर्ता USERPROFILES की तरह कुछ दे रही है? स्थान के आधार पर USERPROFILES फ़िल्टर कर सकते हैं पाने के लिए WCF पर एक आराम सेवा का निर्माण कर रहा हूँ = लंदन

अब मैं निम्न विधि है

GetUserProfiles(string firstname, string lastname, string age, string location) 

एसक्यूएल क्वेरी स्ट्रिंग जो मैंने बनाया है वह है: select firstname, lastname, .... from profiles where (firstName like '%{firstname}%') AND (lastName like '%{lastName}%') .... और इसलिए सभी चर स्ट्रिंग फॉर्मेटर द्वारा प्रतिस्थापित किए जा रहे हैं।

इस के साथ समस्या यह है कि यह .... firstname, lastname, आयु या स्थान एक शून्य मान होने किसी भी पंक्ति फिल्टर है

कर (firstName like '%{firstName}%' OR firstName IS NULL) की तरह कुछ कठिन हो सकता है और बयान unmaintanable बन जाएगा! (इस उदाहरण में केवल 4 तर्क हैं, लेकिन मेरी वास्तविक विधि में 10)

इसके लिए सबसे अच्छा समाधान क्या होगा? .... यह स्थिति आमतौर पर कैसे संभाली जाती है?

डाटाबेस का इस्तेमाल किया: MySql

+0

क्या आपने LINQ-to-SQL का उपयोग करने पर विचार किया है? –

+0

नहीं, मैंने अभी तक linq को sql नहीं माना है ... –

उत्तर

1

आप उपयोग कर सकते हैं COALESCE(value,...)

coalesce(firstName, '') like '%{firstname}%' 
+1

'COALESCE()' मूल रूप से एक ओ (एन) लुकअप है क्योंकि कोई अनुक्रमणिका का उपयोग नहीं किया जाएगा। – cletus

2

यह NULL की एक मौलिक संपत्ति है कि जब आप यह कुछ भी — जिसके कारण है कि तुम क्या काम नहीं करता है क्या कर रहे हैं NULL — यह रिटर्न false सहित, के लिए की तुलना करें।

तो जवाब देने वाला पहला सवाल यह है: आप NULLlastname के साथ पंक्ति क्यों चाहते हैं जब वे "स्मिथ" के lastname दर्ज करते हैं? संभवतः आपका मतलब है कि या तो पहला नाम या अंतिम नाम लौटने के लिए मिलान करने की आवश्यकता है, इस स्थिति में आप सही क्वेरी नहीं चला रहे हैं। सबसे अनुभवहीन समाधान है:

SELECT firstname, lastname, .... 
FROM profiles 
WHERE IFNULL(firstName LIKE'%{firstname}%' 
OR lastName LIKE '%{lastName}%' 

अब इस सैकड़ों और कई हजार संभवतः पंक्तियों के लिए काम करेंगे, लेकिन कई कारणों से परे स्केल नहीं करेगा:

  1. OR रों के मामले में आम तौर पर कर रहे हैं खस्ताहाल प्रदर्शन। जहां संभव हो उनसे बचें। यदि आप अनुभवी प्रोग्रामर द्वारा लिखे गए डेटाबेस अनुप्रयोगों को देखते हैं तो आपको शायद एक OR स्थिति नहीं मिलेगी (उन लोगों को छोड़कर जो OR के गुणों को संभावित रूप से अतिथि पुस्तिका में लिखे गए हैं, जिसमें 3 उपयोगकर्ता और 2 महीने में हिट होते हैं) ;
  2. LIKE को % के साथ फ्रंट पर मतलब होगा कि कोई अनुक्रमणिका पर मुकदमा नहीं किया जाएगा।

(2) के कई समाधान हैं। शायद MySQL में सबसे आसान है MyISAM तालिकाओं पर full text searching का उपयोग करना है। यदि आप "हन" टाइप करते हैं तो यह "जोहान्स" जैसे मैचों को नहीं मिलेगा लेकिन यह आमतौर पर पर्याप्त है।

अक्सर आप UNION या (अधिमानतः) UNION ALL का उपयोग करके कई प्रश्नों पर OR स्थितियों से निपटते हैं। उदाहरण के लिए:

SELECT firstname, lastname, .... 
FROM profiles 
WHERE firstName LIKE'%{firstname}%' 
AND lastName LIKE '%{lastName}%' 
UNION ALL 
SELECT firstname, lastname, .... 
FROM profiles 
WHERE firstName LIKE'%{firstname}%' 
AND lastname IS NULL 
UNION ALL 
SELECT firstname, lastname, .... 
FROM profiles 
WHERE firstName IS NULL 
AND lastName LIKE '%{lastName}%' 
UNION ALL 
SELECT firstname, lastname, .... 
FROM profiles 
WHERE firstName IS NULL 
AND lastName IS NULL 

बड़ा और बदसूरत लेकिन UNION ALL तराजू बहुत अच्छी तरह से (LIKE मापदंड के शुरू में % अनदेखी) लग रहा है। यह मूल रूप से सम्मिलित है (इस मामले में) चार प्रश्न। UNION परिणाम पंक्तियों पर एक अंतर्निहित DISTINCT करेगा लेकिन हम जानते हैं कि यहां कोई ओवरलैप नहीं होगा क्योंकि हम NULL के लिए अलग-अलग जांच कर रहे हैं।

एक और संभावना NULL का इलाज करने के लिए कुछ नहीं है जिसे आप खोजना चाहते हैं। यह एक बहुत बेहतर और अधिक सहज समाधान (imho) है। अगर कोई "स्मिथ" के अंतिम नाम में टाइप करता है, तो क्या आप वास्तव में NULL अंतिम नाम दिखाते हुए पंक्तियां चाहते हैं?

या क्या आप उन्हें दिखाना चाहते हैं क्योंकि आपको पहले नाम पर एक मैच मिल सकता है? यदि ऐसा है, तो आप थोड़ा अलग सवाल चाहते हैं। उदाहरण के लिए:

SELECT firstname, lastname, .... 
FROM profiles 
WHERE id IN (
    SELECT id 
    FROM profiles 
    WHERE firstName LIKE'%{firstname}%' 
    UNION ALL 
    SELECT id 
    FROM profiles 
    WHERE lastName LIKE '%{lastName}%' 
) 
+0

इतने सारे यूनियनों के साथ प्रदर्शन ?? –

+0

@glenn: जैसा कि मैंने कहा था, इस मामले में चार यूनियन संस्करण अधिकतर व्यर्थ ** होने जा रहा है ** क्योंकि मानदंड इंडेक्स का उपयोग नहीं करेंगे, लेकिन यदि आप इंडेक्स का उपयोग कर रहे थे तो यह एक अलग कहानी है। बड़ा मुद्दा यह है कि क्या आप सही क्वेरी चला रहे हैं और क्या आपका डेटा मॉडल उप-शीर्ष है या नहीं। – cletus

0

आप COALESCE उपयोग कर सकते हैं:

select firstname, lastname, .... 
from profiles 
where (coalesce(firstName, '') like '%{firstname}%') 
AND (coalesce(lastName, '') like '%{lastName}%') 
+1

'COALESCE()' मूल रूप से एक ओ (एन) लुकअप है क्योंकि कोई अनुक्रमणिका का उपयोग नहीं किया जाएगा। – cletus

+1

हां, जाहिर है, लेकिन आप 'LIKE'% foo% 'की वजह से इंडेक्स का उपयोग नहीं कर सकते हैं, इसलिए यह यहां एक महत्वपूर्ण बिंदु प्रतीत होता है। इंडेक्स का उपयोग 'LIKE' foo% 'के साथ किया जा सकता है लेकिन शुरुआत में वाइल्डकार्ड नहीं है। यदि प्रदर्शन यहां एक मुद्दा है, तो एक पूर्ण पाठ अनुक्रमणिका का उपयोग किया जाना चाहिए। –

0

तुम हमेशा पहली जगह में शून्य मान नामंज़ूर सकता है - सब के बाद, हर कोई होना चाहिए कुछ सकारात्मक संख्या के लिए जीवित और भौगोलिक दृष्टि से कहीं भी।

यदि आपको बिल्कुल नल की अनुमति देनी है, तो या तो COALESCE का उपयोग करें, जैसा कि अन्य ने सुझाव दिया है, या संभवतः IFNULL जो MySQL विशिष्ट है और यह थोड़ा अधिक इष्टतम हो सकता है क्योंकि यह वास्तव में 2 पैरामीटर लेता है।

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