ANSI SQL NUM के रूप में SUM (कोई पंक्तियाँ) को परिभाषित क्यों नहीं करता है?


28

ANSI SQL मानक परिभाषित करता है (अध्याय 6.5, सेट समारोह विनिर्देश) खाली परिणाम सेट पर कुल कार्यों के लिए निम्नलिखित व्यवहार:

COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL

औसत, न्यूनतम और अधिकतम के खाली होने के बाद AVG, MIN और MAX के लिए रिटर्निंग पूर्ण समझ में आता है, अपरिभाषित है।

अंतिम, हालांकि, मुझे परेशान करता है: गणितीय रूप से, एक खाली सेट का एसयूएम अच्छी तरह से परिभाषित है 0:। 0 का उपयोग, तटस्थ तत्व के अलावा, जैसा कि आधार मामला सब कुछ सुसंगत बनाता है:

SUM({})        = 0    = 0
SUM({5})       = 5    = 0 + 5
SUM({5, 3})    = 8    = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL

मूल SUM({})रूप nullसे परिभाषित करने से "कोई पंक्तियाँ नहीं" एक विशेष मामला बन जाता है जो दूसरों के साथ फिट नहीं होता है:

SUM({})     = NULL  = NULL
SUM({5})    = 5    != NULL + 5 (= NULL)
SUM({5, 3}) = 8    != NULL + 5 + 3 (= NULL)

क्या उस विकल्प का कुछ स्पष्ट लाभ था जिसे (SUM NULL होने के नाते) याद किया गया था?



5
हां मैं सहमत हूं: COUNT और SUM लगातार व्यवहार नहीं करते हैं।
एके

जवाबों:


20

मुझे डर है कि इसका कारण यह है कि नियमों को एक एडहॉक फैशन में सेट किया गया था (जैसे कि आईएसओ एसक्यूएल मानक के कई अन्य "फीचर्स" ) ऐसे समय में जब एसक्यूएल एग्रीगेशन और गणित के साथ उनके संबंध अब की तुलना में कम समझ में आए थे। (*)।

यह SQL भाषा में बहुत अधिक विसंगतियों में से एक है। वे भाषा को सिखाने के लिए कठिन, सीखने के लिए कठिन, समझने के लिए कठिन, उपयोग करने के लिए कठिन, जो भी आप चाहते हैं के लिए कठिन बनाते हैं, लेकिन यह सिर्फ चीजें हैं। पिछड़े संगतता के स्पष्ट कारणों के लिए नियमों को "ठंडा" और "उस तरह" नहीं बदला जा सकता है, (यदि आईएसओ समिति मानक का अंतिम संस्करण प्रकाशित करती है, और विक्रेता तब उस मानक को लागू करने के लिए निर्धारित होते हैं, तो वे विक्रेता सराहना नहीं करेंगे। यदि बाद के संस्करण में यह बहुत अधिक है, तो नियम बदल दिए जाते हैं, जो मानक के पूर्व संस्करण के मौजूदा (आज्ञाकारी) कार्यान्वयन "नए संस्करण का अनुपालन करने में स्वचालित रूप से विफल" ...)

(*) यह अब बेहतर समझा जाता है कि खाली सेट पर एकत्रीकरण अधिक लगातार व्यवहार करते हैं यदि वे व्यवस्थित रूप से पहचान मूल्य (= जिसे आप 'एलीमेंट एलीमेंट' कहते हैं) को अंतर्निहित बाइनरी ऑपरेटर के हाथ में लौटा देते हैं । COUNT और SUM के लिए अंतर्निहित बाइनरी ऑपरेटर इसके अतिरिक्त है, और इसका पहचान मूल्य शून्य है। MIN और MAX के लिए, यह पहचान मूल्य हाथ में प्रकार का उच्चतम और निम्नतम मूल्य है, क्रमशः, यदि संबंधित प्रकार परिमित हैं। औसत, हार्मोनिक साधनों, मध्यस्थों आदि जैसे मामले इस संबंध में बेहद जटिल और विचित्र हैं।


मुझे लगता है कि शून्य से मिनट और अधिकतम के साथ एक खाली सेट पर समझ में आता है। आप कह सकते हैं कि एक पहचान मूल्य वास्तव में अज्ञात है, लेकिन कोई भी मान का योग 0 नहीं है इसी कारण से n * 0 हमेशा 0. होता है, लेकिन न्यूनतम और अधिकतम भिन्न होते हैं। मुझे नहीं लगता कि परिणाम ठीक से बिना किसी रिकॉर्ड के चल रहा है।
क्रिस ट्रैवर्स

एक अशक्त सेट पर भी avg () शून्य के रूप में समझ में आता है क्योंकि 0/0 इस संदर्भ में ठीक से परिभाषित नहीं है।
क्रिस ट्रैवर्स

5
MIN और MAX इतने अलग नहीं हैं। एक अंतर्निहित बाइनरी ऑपरेटर लोवेस्टोफ़ (एक्स, वाई) और हाईएस्टॉफ़ (एक्स, वाई) क्रमशः लें। इन बाइनरी ऑपरेटरों का एक पहचान मूल्य होता है। क्योंकि दोनों मामलों में (यदि शामिल प्रकार परिमित है), तो वास्तव में कुछ मूल्य z मौजूद है जैसे कि forall x: LOWESTOF (z, x) = x और forall y: HIGHESTOF (y, z) = y। (पहचान का मूल्य दोनों मामलों के लिए समान नहीं है, लेकिन यह दोनों मामलों के लिए मौजूद है।) मैं मानता हूं कि परिणाम पहली नज़र में बेहद उलझे हुए लगते हैं, लेकिन गणितीय वास्तविकता से कोई इनकार नहीं करता है।
एरविन स्माउट

@Erwin: मैं अपने सभी बिंदुओं पर सहमत हैं, सिवाय इसके कि कुछ कार्यों, जैसे की पहचान HIGHEST()कई डेटाप्रकार का एक तत्व नहीं हो, जैसे reals के लिए जहाँ पहचान हो जाएगा -Infinity(और +Infinityके लिए LOWEST())
ypercubeᵀᴹ

1
@ SQL कीवी क्या आप स्थैतिक प्रकार की जाँच के बारे में भूल रहे हैं? यदि SUM () जैसे भावों को स्थिर प्रकार के चेकर द्वारा नियंत्रित किया जाता है जैसे कि वे हमेशा एक पूर्णांक लौटाते हैं, तो जाहिर है कि SUM () मंगलाचरण के लिए कभी-कभी कुछ ऐसा लौटाया जाना चाहिए जो पूर्णांक नहीं हो (जैसे एक खाली संबंध)।
इरविन स्माउट

3

व्यावहारिक अर्थों में मौजूदा परिणाम NULLउपयोगी है। निम्नलिखित तालिका और कथनों पर विचार करें:

C1 C2
-- --
 1  3 
 2 -1 
 3 -2 

SELECT SUM(C2) FROM T1 WHERE C1 > 9;

SELECT SUM(C2) FROM T1 WHERE C1 < 9;

पहला कथन NULL और दूसरा शून्य देता है। अगर एक खाली सेट शून्य के लिए लौटा, SUMतो हमें एक खाली सेट से शून्य का सही योग भेद करने के लिए एक और साधन की आवश्यकता होगी, शायद गिनती का उपयोग करके। यदि हम वास्तव में खाली सेट के लिए शून्य चाहते हैं, तो एक साधारण COALESCEउस आवश्यकता को प्रस्तुत करेगा।

SELECT COALESCE(SUM(C2),0) FROM T1 WHERE C1 > 9;

1
परिणामस्वरूप।, SUM (सेट 1 और सेट 2 का मिलन) <> SUM (सेट 1) + SUM (सेट 2), क्योंकि कोई भी संख्या + NULL = NULL। क्या तुम्हें इसका कोई मतलब लगता है?
AK 15

2
@Leigh: COALESCE()इस तरह का उपयोग करने से ( 0) योग से खाली सेट का अंतर ( ) योग नहीं होगा NULL(कहते हैं कि तालिका में एक (10, NULL)पंक्ति थी।
ypercubeᵀᴹ

इसके अलावा, हम अभी भी SUM (एक या अधिक NULLs के सेट) से SUM (खाली सेट) को अलग नहीं कर सकते हैं। क्या हमें बिल्कुल अलग होने की जरूरत है?
AK 14

@AlexKuznetsov - हम एक सेट के योग से एक खाली सेट की राशि को अलग कर सकते हैं जिसमें एक या अधिक नल होते हैं जब तक कि कम से कम एक पंक्ति में एक मूल्य नहीं होता। आप सही हैं कि यदि सेट में केवल NULLs हैं तो हम NULL सेट को सभी NULL मानों के इस सेट से अलग नहीं कर सकते। मेरा कहना यह नहीं था कि यह हर मामले में उपयोगी है, केवल यह उपयोगी हो सकता है। यदि मुझे SUMकोई कॉलम मिलता है और शून्य मिलता है, तो मुझे पता है कि जाँच करने के लिए कम से कम एक NULL पंक्ति नहीं है जिसका उपयोग मुझे परिणाम दिखाने के लिए किया जा रहा है।
लेह रिफेल

@ypercude - आप बिल्कुल सही हैं। मेरा कहना यह था कि SUM का वर्तमान व्यवहार एक सेट से खाली सेट को अलग करता है जिसमें मान होते हैं (भले ही कुछ अशक्त हों)। COALESCE का उपयोग करना तब सरल होता है जब भेद किसी वस्तु का उपयोग करने की आवश्यकता नहीं है DECODE(count(c2),0,NULL,sum(c2))जब वह है।
लीघ रिफ़ेल

-1

मुख्य अंतर जो मैं देख सकता हूं वह डेटाटाइप के संबंध में है। COUNT में एक अच्छी तरह से परिभाषित वापसी है: एक पूरी संख्या। अन्य सभी उस कॉलम / अभिव्यक्ति के प्रकार पर निर्भर करते हैं जो वे देख रहे हैं। उनका रिटर्न प्रकार सेट के सभी सदस्यों के साथ संगत होना चाहिए (फ़्लोट, मुद्रा, दशमलव, बीसीडी, टाइमपेन, ...)। चूंकि कोई सेट नहीं है इसलिए आप रिटर्न प्रकार नहीं दे सकते हैं, इस प्रकार NULL आपका सबसे अच्छा विकल्प है।

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


5
हम SUM(column)अभिव्यक्ति में रिटर्न टाइप क्यों नहीं कर सकते ? क्या हमारे पास खाली टेबल नहीं हैं - और क्या सभी कॉलमों में परिभाषित प्रकार हैं? खाली रिजल्ट सेट के लिए यह अलग क्यों होना चाहिए?
ypercube y

5
आपको यह गलत लगता है जहां आप कहते हैं "चूंकि कोई सेट नहीं है "। एक सेट है। शामिल कॉलम या अभिव्यक्ति के घोषित प्रकार के सभी संभावित मूल्यों का सेट। यह घोषित प्रकार मौजूद है भले ही आप जिस तालिका को देख रहे हैं वह खाली है। यहां तक ​​कि खाली टेबल में अभी भी हेडिंग है। और वह घोषित प्रकार आपका "निहित रिटर्न प्रकार" है।
इरविन स्मौट

क्या तुम दोनों ने वास्तव में मेरा नोट पढ़ा है? हां, यह कॉलम-आधारित SUM के लिए अब तक काम करेगा। लेकिन जैसे ही आप एक चर डेटाटाइप-कॉलम (एसक्यूएल सर्वर में - अभी तक नहीं) का सामना करते हैं, आप भाग्य से बाहर हैं।
TToni

2
आप उस मामले में राशि को कैसे परिभाषित करेंगे? क्या होगा परिणाम 24 + 56.07 + '2012-10-05' + 'Red'? मेरा मतलब है कि चिंता करने की कोई बात नहीं है कि SUM()जब हम समस्या को परिभाषित करने के साथ-साथ व्यवहार कैसे करेंगे।
ypercube y

1
@TToni: "विशेष रूप से जब आप मानक के संभावित विस्तार के बारे में सोचते हैं" वह संदर्भ नहीं है जिसे ओपी संदर्भित कर रहा था। ओपी मानक के वर्तमान संस्करण का बहुत स्पष्ट रूप से उल्लेख कर रहा था, जिसमें किसी भी प्रकार की "गतिशील प्रकार" या कुछ इस तरह की धारणा शामिल नहीं है। (। ओह, और मैं केवल टिप्पणी की है, लेकिन है कि छोटे पर्ची मैं के साथ इस मुद्दे को ले लिया से downvote नहीं था के अलावा, आपका जवाब में कुछ भी नहीं एक downvote वारंट गलत पर्याप्त था IMO।।)
इरविन Smout
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.