2010-02-24 13 views
6

मुझे डेटाबेस से उच्चतम मूल्य प्राप्त करने की आवश्यकता है जो एक निश्चित स्वरूपण सम्मेलन को पूरा करता है। विशेष रूप से, मैं के लिए उच्चतम मूल्य उस तरहटी-एसक्यूएल IsNumeric() और लिंक-टू-एसक्यूएल

EU999999 ('9' किसी भी अंकों किया जा रहा है)

चयन अधिकतम (col) की तरह कुछ वापस आ जाएगी लग रहा है पता लगाने के लिए चाहते हैं 'EUZ ...' उदाहरण है कि मैं बाहर करना चाहता हूँ। निम्न क्वेरी चाल करता है, लेकिन मैं इसे लिंक-टू-एसक्यूएल के माध्यम से नहीं बना सकता। ऐसा लगता है कि SQL सर्वर में isnumeric() फ़ंक्शन के लिए कोई अनुवाद नहीं है।

select max(col) from table where col like 'EU%' 
    and 1=isnumeric(replace(col, 'EU', '')) 

एक डेटाबेस समारोह, संग्रहीत प्रक्रिया, या कि प्रकृति के कुछ और लेखन, अब तक मेरी पसंदीदा समाधान के इस सूची में नीचे है, क्योंकि इस तालिका मेरे ऐप के लिए महत्वपूर्ण है और मुझे नहीं आसानी से कुछ और के साथ तालिका वस्तु की जगह ले सकता ।

अगला सबसे अच्छा समाधान क्या है?

उत्तर

10

हालांकि ISNUMERIC याद आ रही है, तो आप हमेशा की कोशिश कर सकते लगभग बराबर NOT LIKE '%[^0-9]%, यानी, वहाँ स्ट्रिंग में कोई गैर अंकों, या वैकल्पिक रूप, स्ट्रिंग खाली है या केवल अंक के होते हैं:

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9]%') // starts with EU and at least one digit 
    && !SqlMethods.Like(x.col, '__%[^0-9]%') // and no non-digits 
select x; 

बेशक, अगर आप जानते हैं कि अंकों की संख्या तय हो गई है, इस

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9][0-9][0-9][0-9][0-9][0-9]') 
select x; 
+0

मुझे आपका सुझाव पसंद है और मैं इसे स्वीकार करूंगा, लेकिन मेरा उपसर्ग (और लंबाई) निरंतर नहीं है, दुर्भाग्यवश, इसलिए मुझे अभिव्यक्ति को गतिशील रूप से उत्पन्न करना होगा। मुझे पसंद नहीं है, और मैं स्कीमा को बदलने के तरीकों के बारे में सोच रहा हूं ताकि मैं इसके आसपास काम कर सकूं। – cdonner

+0

सामने वाले वाइल्डकार्ड के साथ 'LIKE' का उपयोग करने के फायदों में से एक यह है कि यह बहुत ही सूचकांक अनुकूल है (इंडेक्स के खिलाफ एक रेंज चेक किया जा सकता है)। – Ruben

+0

परिवर्तनीय लंबाई के अभिव्यक्तियों पर IsNumeric के लिए एक बहुत चालाक विकल्प। स्ट्रिंग में कहीं भी गैर-संख्यात्मक चरित्र की तलाश करें। पारितोषिक के लिए धन्यवाद! – BlueMonkMN

1

को सरल किया जा सकता जैसा कि आपने कहा, वहाँ LINQ से SQL को IsNumeric के लिए कोई अनुवाद है। कुछ विकल्प हैं, आपने पहले ही डेटाबेस फ़ंक्शन और संग्रहीत प्रक्रिया को लिखा है। मुझे दो और जोड़ना पसंद है।

विकल्प 1: आप LINQ मिश्रण वस्तुओं के लिए LINQ के साथ SQL करने के लिए ऐसा कर सकते हैं, लेकिन जब आप एक बड़ा डेटाबेस मिल गया है, शानदार प्रदर्शन की उम्मीद नहीं है:

var cols = (from c in db.Table where c.StartsWith("EU") select c).ToList(); 
var stripped = from c in cols select int.Parse(c.Replace("EU", "")); 
var max = stripped.Max(); 

विकल्प 2: बदलने अपने डेटाबेस स्कीमा :-)

+0

कोई विकल्प नहीं - इस तालिका में बहुत अधिक डेटा है। – cdonner

+0

अभी भी, मेरी स्कीमा बदलने के सुझाव के लिए +1। – cdonner

10

आप डेटा कॉन्टेक्स्ट के लिए आंशिक कक्षा में एक विधि जोड़कर ISNUMERIC फ़ंक्शन का उपयोग कर सकते हैं। यह एक यूडीएफ का उपयोग करने के समान होगा।

अपने DataContext के आंशिक वर्ग में इस जोड़ें:

var query = dc.TableName 
       .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") }) 
       .Where(p => SqlMethods.Like(p.Col, "EU%") 
         && dc.IsNumeric(p.ReplacedText) == 1) 
       .OrderByDescending(p => p.ReplacedText) 
       .First() 
       .Col; 

Console.WriteLine(query); 

या आप बना सकते हैं उपयोग मैक्स:

var query = dc.TableName 
       .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") }) 
       .Where(p => SqlMethods.Like(p.Col, "EU%") 
        && dc.IsNumeric(p.ReplacedText) == 1); 

var result = query.Where(p => p.ReplacedText == query.Max(p => p.ReplacedText)) 
        .First() 
        .Col; 

Console.WriteLine("Max: {0}, Result: {1}", max, result); 

partial class MyDataContext 
{ 
    [Function(Name = "ISNUMERIC", IsComposable = true)] 
    public int IsNumeric(string input) 
    { 
     throw new NotImplementedException(); // this won't get called 
    } 
} 

फिर अपने कोड इस तरह से यह प्रयोग करेंगे आपके अंतिम लक्ष्य के आधार पर max चर पर रोकना संभव हो सकता है और इसे " यूरोपीय संघ "पाठ को दूसरी क्वेरी से बचने के लिए जो कॉलम नाम प्राप्त करता है।

संपादित करें: टिप्पणी में उल्लेख किया, इस दृष्टिकोण की कमी है कि आदेश पाठ के बजाय संख्यात्मक मान पर किया जाता है और वहाँ वर्तमान में एसक्यूएल पर Int32.Parse के लिए कोई अनुवाद है।

+0

+1। मैं बहुत आश्चर्यचकित हूं यह संभव है। ऑर्डरिंग को न भूलें * ऑर्डरबैडसेकेंडिंग (पी => पी। रीप्लेस्ड टेक्स्ट) * टेक्स्ट आधारित है (रीप्लेस्ड टेक्स्ट एक स्ट्रिंग/वर्कर है), इसलिए यह उचित परिणाम नहीं दे सकता है। इसे सॉर्ट करने से पहले एक पूर्णांक में डालना होगा। – Steven

+0

@ स्टीवन धन्यवाद, यह सरल कार्यों के लिए एक साफ कामकाज है। आप आदेश के बारे में सही हैं। दुर्भाग्य से इसके लिए कोई कामकाज नहीं है और 'Int32.Parse' के पास एसक्यूएल में कोई अनुवाद नहीं है, इसलिए वास्तविक यूडीएफ/एसपीआरओसी संख्यात्मक सॉर्टिंग के लिए सबसे अच्छा है। –

+0

वही है, यह थोड़ी देर में देखी गई सबसे छोटी चीजों में से एक है। – cdonner

0

मेरे सुझाव वापस में लाइन एसक्यूएल करने के लिए आते हैं और DataContext.ExecuteQuery() विधि का प्रयोग है। आप शुरुआत में पोस्ट की गई SQL क्वेरी का उपयोग करेंगे।

इसी तरह की स्थितियों में मैंने यही किया है। टाइप-चेकिंग और संभावित सिंटैक्स त्रुटियों की कमी के कारण आदर्श नहीं दिया गया है, लेकिन बस सुनिश्चित करें कि यह किसी यूनिट परीक्षण में शामिल है। लिंकक सिंटैक्स द्वारा प्रत्येक संभावित क्वेरी को कवर नहीं किया जाता है, इसलिए पहले स्थान पर ExecuteQuery का अस्तित्व।

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