2009-05-11 10 views
11

मैं कुछ खराब रूप से बनाए गए XML स्तंभों में संग्रहीत मौद्रिक रकम निकालने का प्रयास कर रहा हूं (एक्सएमएल कॉलम के लिए कोई स्कीमा परिभाषित नहीं है जो मुझे लगता है कि समस्या का हिस्सा है)। जब भी मुझे 0 के साथ नोड का सामना करना पड़ता है तो मुझे एक रूपांतरण त्रुटि मिल रही है।शून्य सर्वर पर SUM कर रहे SQL सर्वर में XQuery

उदाहरण:

select xml.value('sum(/List/value)', 'numeric') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

त्रुटि को जन्म देती है:

select xml.value('sum(/List/value)', 'numeric') sum 
from (select cast('<List><value>1</value><value>2</value></List>' as xml) xml) a 

राशि 3 जबकि देता है "। त्रुटि सांख्यिक को बदलने डेटा प्रकार nvarchar"

कोई विचार नहीं कि शून्य-मूल्यवान नोड्स की सूची को सारांशित करते समय मैं अपनी क्वेरी को वापस कैसे कर सकता हूं?

+3

ऐसा लगता है कि राशि (/ सूची/मान) एक फ्लोट "0.0E0" लौटाती है जब योग शून्य होता है और उस संख्या को संख्यात्मक रूप में परिवर्तित नहीं किया जा सकता है। कोई विचार क्यों मैं इस व्यवहार को देखता हूं? –

उत्तर

6

आपकी टिप्पणी आपकी समस्या का उत्तर देती है।

संख्यात्मक रूपांतरित करने के बजाय, फ्लोट में कनवर्ट करने के बजाय। वैज्ञानिक नोटेशन फ्लोट में परिवर्तित हो जाएगा।

3

आप भी उपयोग कर सकते हैं और इस तरह से बयान करता है, तो:

@x.value('if (sum(/List/value) = 0) then 0 else sum(/List/value)', 'numeric') 
3

मैं इस सवाल के पार एक जवाब ठोकर खाई है, और अंततः, जबकि पूर्णांकों के साथ एक समान मुद्दा को देखकर। आखिरी उत्तर के बाद देरी के बावजूद, अगर मैं भविष्य में किसी और की मदद करता हूं तो मैं यहां जोड़ रहा हूं।

सबसे पहले अपने बुनियादी जवाब:

select xml.value('xs:decimal(sum(/List/value))', 'numeric') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

XQuery में आप एक मानक XML स्कीमा प्रकार है, जो तब SQL सर्वर द्वारा सही ढंग से नियंत्रित किया जाएगा करने के लिए मूल्य डाल सकता।

कृपया ध्यान दें: SQL सर्वर में डिफ़ॉल्ट "संख्यात्मक" में कोई दशमलव स्थान नहीं है ("0" का स्तर)!

अंत में, वास्तविक

select xml.value('xs:decimal(sum(/List/value))', 'numeric(20,5))') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

(आप Xml से दिए गए मान से सटीक या पैमाने अनुमान लगाने के लिए एसक्यूएल सर्वर नहीं मिल सकता है, आप स्पष्ट रूप से यह निर्दिष्ट करना होगा): आप शायद और अधिक की तरह कुछ क्या करने का इरादा मुद्दा यह है कि मैं व्यक्तिगत रूप से पता करने के लिए आवश्यक है, लगभग ठीक उसी था सिवाय मैं पूर्णांकों, जो भी "0" double मूल्यों की एक्सएमएल प्रतिनिधित्व के साथ संघर्ष के साथ काम कर रहा था:

select xml.value('xs:int(sum(/List/value))', 'int') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

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

select xml.value('xs:decimal(sum(/List/value))', 'numeric(28, 0)') sum 
from (select cast('<List> 
     <value>1000000000000000000000000001</value> 
     <value>1000000000000000000000000001</value> 
    </List>' as xml) xml) a 

("2000000000000000000000000000" करने के लिए बाहर आता है, जो गलत है)

यह समस्या समान रूप से इस तरह के स्पष्ट रूप से के रूप में यहाँ की पेशकश की अन्य तरीकों, पर लागू होता है: यहाँ ईजी हम नंबर हम संक्षेप रहे हैं की पिछले अंक खोना मूल्य को टी-एसक्यूएल में "फ्लोट" के रूप में पढ़ना।

इससे बचने के लिए, डेटा प्रकार को एग्रीगेशन ऑपरेशन से पहले सेट करने के लिए XQuery FLWOR अभिव्यक्ति का उपयोग करके अंतिम विकल्प यहां दिया गया है। इस मामले में, एकत्रीकरण सही ढंग से होता है, और हम सही अभिव्यक्त मूल्य (करते हुए भी "0" मूल्यों यदि/जब वे होते हैं निपटने):

select xml.value('sum(for $r in /List/value return xs:decimal($r))', 'numeric(28, 0)') sum 
from (select cast('<List> 
     <value>1000000000000000000000000001</value> 
     <value>1000000000000000000000000001</value> 
    </List>' as xml) xml) a 

("2000000000000000000000000002" करने के लिए बाहर आता है, सही मान)

+0

मुझे मानक एक्सएमएल स्कीमा प्रकार में मान डालने के लिए XQuery का उपयोग करने के तरीके को यहां पसंद है। यही वही था जो मैं खोज रहा था, और इसे एक फ्लोट में परिवर्तित करने के लिए, और फिर किसी और चीज़ पर वापस लेना पसंद करता हूं। यह थोड़ा और स्पष्ट है, लेकिन मैं इसे एक प्रकार और फिर दूसरे स्थान पर ले जाने से बच सकता हूं, और मुझे लगता है कि यह स्पष्ट है। – mttjohnson