इस क्वेरी के लिए सही परिणाम क्या है?


20

मैं इस पहेली में यहाँ टिप्पणियों में आया था

CREATE TABLE r (b INT);

SELECT 1 FROM r HAVING 1=1;

SQL सर्वर और PostgreSQL 1 पंक्ति लौटाता है।

MySQL और Oracle शून्य पंक्तियाँ लौटाते हैं।

क्या सही है? या दोनों समान रूप से मान्य हैं?


अच्छी पहेली। मुझे लगता है कि सही 1 पंक्ति वापस करना है। SQL-Server स्वयं विरोधाभासी है क्योंकि SELECT COUNT(*) FROM r;1 पंक्ति (साथ 0) SELECT COUNT(*) FROM r GROUP BY ();देता है , जबकि कोई पंक्तियाँ नहीं देता है।
ypercube y

1
और चाहिए? SELECT 1 WHERE 1=0 HAVING 1=1;SQL सर्वर और PostgreSQL अभी भी एक पंक्ति लौटाते हैं। ओरेकल डीयूएल से चाहता है और कोई पंक्तियां नहीं लौटाता है। MySQL न तो डीयूएल से और न ही इसके बिना संकलित करता है
एंड्री एम

1
@AndriyM कुछ अज्ञात कारण के लिए "दोहरी" और "HAVING" MySQL में अच्छा नहीं खेलता है। (अच्छी खोज)। लेकिन समतुल्य कार्य: SELECT 1 AS t FROM (SELECT 1) tmp WHERE 1=0 HAVING 1=1; 1-पंक्ति-नो-डुअल और 0 पंक्तियों को लौटाता है।
ypercube y

1
@SQLKiwi - कल्पना से इस मार्ग के बारे में क्या। "यदि टीई में तुरंत ए नहीं है <group by clause>, तो “GROUP BY ()”निहित है।" क्या दोनों प्रश्नों को एक ही परिणाम नहीं देना चाहिए?
मार्टिन स्मिथ

1
लेकिन इन पर असहमति (ओरेकल HAVINGअलग तरीके से प्रश्नों को निष्पादित करता है ): SQl-fiddle 2:
HAVING

जवाबों:


17

मानक के अनुसार:

SELECT 1 FROM r HAVING 1=1

माध्यम

SELECT 1 FROM r GROUP BY () HAVING 1=1

उद्धरण आईएसओ / IEC 9075-2: 2011 7.10 सिंटेक्स नियम 1 (हवलदार पुरस्कार की परिभाषा का हिस्सा):

आज्ञा देना HCहो <having clause>। आज्ञा TEदेना है <table expression>कि तुरंत शामिल हैं HC। यदि TEतुरंत नहीं है <group by clause>, तो " GROUP BY ()" निहित है। आज्ञा देना Tतालिका के विवरणक के रूप में परिभाषित किया गया <group by clause> GBCहै जिसमें निहित है TEऔर Rइसका परिणाम होने दें GBC

ठीक है तो बहुत स्पष्ट है।


कथन: 1=1सत्य खोज स्थिति है। मैं इसके लिए कोई उद्धरण नहीं दूंगा।


अभी

SELECT 1 FROM r GROUP BY () HAVING 1=1

के बराबर है

SELECT 1 FROM r GROUP BY ()

प्रशस्ति पत्र आईएसओ / आईईसी 9075-2: 2011 7.10 सामान्य नियम 1:

<search condition>के प्रत्येक समूह के लिए मूल्यांकन किया जाता है R। का परिणाम <having clause>R के उन समूहों की एक समूहीकृत तालिका है जिसके लिए परिणाम <search condition>सत्य है।

लॉजिक: चूँकि सर्च की स्थिति हमेशा सही होती है, परिणाम है R, जो कि अभिव्यक्ति द्वारा समूह का परिणाम है।


निम्नलिखित 7.9 के सामान्य नियमों का एक अंश है (समूह की परिभाषा CLAUSE द्वारा)

1) यदि कोई <where clause>निर्दिष्ट नहीं है, तो Tपूर्ववर्ती परिणाम होने दें <from clause>; अन्यथा, Tपूर्ववर्ती परिणाम होने दें <where clause>

2) मामला:

a) यदि कोई समूहीकरण स्तंभ नहीं हैं, तो <group by clause>समूहित तालिका का परिणाम Tउसके एकमात्र समूह के रूप में है।

इस प्रकार हम यह निष्कर्ष निकाल सकते हैं

FROM r GROUP BY ()

एक समूह तालिका में परिणाम, एक समूह से मिलकर, शून्य पंक्तियों के साथ (चूंकि आर खाली है)।


7.12 के सामान्य नियमों का एक अंश, जो एक क्वेरी विशिष्टता (उर्फ ए सलेक्ट स्टेटमेंट) को परिभाषित करता है:

1) मामला:

क) यदि Tएक समूहीकृत तालिका नहीं है, तो [...]

ख) यदि Tएक समूहीकृत तालिका है, तो

मामला:

i) यदि T0 (शून्य) समूह हैं, तो TEMP को एक खाली तालिका होने दें।

ii) यदि Tएक या एक से अधिक समूह हैं, तो प्रत्येक <value expression>को पंक्तियों की Tएक तालिका बनाने के प्रत्येक समूह पर लागू किया जाता है , जहां समूहों की संख्या है । अस्थायी की मई के स्तंभ मान के मूल्यांकन द्वारा प्राप्त होता है मई । [...]TEMPMMTii<value expression>

2) मामला:

a) यदि <set quantifier> DISTINCTनिर्दिष्ट नहीं है, तो का परिणाम <query specification>है TEMP

इसलिए चूंकि तालिका में एक समूह है, इसलिए इसमें एक परिणाम पंक्ति होनी चाहिए।

इस प्रकार

SELECT 1 FROM r HAVING 1=1

1 पंक्ति परिणाम सेट वापस करना चाहिए।

QED


+1 सभी परेशानी में जाने के लिए धन्यवाद! जैसा कि @ypercube का कहना है कि SQL Server यहाँ खुद को विरोधाभास के रूप में 1 समूह आर (BY) से चुनें; शून्य पंक्तियाँ लौटाता है लेकिन आपके द्वारा उद्धृत मार्ग इस बिंदु पर काफी स्पष्ट लगता है।
मार्टिन स्मिथ

क्या मैं पूछ सकता हूं कि आपको मानक कहां मिला? अगर आप कहते हैं कि 'मेरे बुकशेल्फ़ पर' मैं निराश हो
जाऊंगा

तकनीकी रूप से मैंने मानक के बजाय फाइनल ड्राफ्ट इंटरनेशनल स्टैंडर्ड का उपयोग किया। ISO / IEC प्रति नियम केवल संपादकीय (गैर-तकनीकी) परिवर्तन FDIS और अंतिम मानक के बीच अनुमत हैं। मानक कई भागों में बँधा हुआ है। भाग 1 , भाग 2 , भाग 4 ...
केविन कैथार्ट

भाग ११ , और भाग १४ । 2011 में पार्ट्स 3,9,10 और 13 अपडेट नहीं किए गए थे, और इस तरह उनके पिछले संस्करण लागू होते हैं। कोई भाग 12 नहीं है। इसी प्रकार 5-8 भाग नहीं हैं। Sql: 2011 या भाग 1 के विकिपीडिया पृष्ठ को स्वयं देखें कि प्रत्येक भाग में क्या है।
केविन कैथार्ट

7

जब एक HAVINGखंड है, एक WHEREखंड के बिना :

SELECT 1 FROM r HAVING 1=1;

... तो GROUP BY ()निहित है। तो, क्वेरी के बराबर होना चाहिए:

SELECT 1 FROM r GROUP BY () HAVING 1=1;

... जो तालिका की सभी पंक्तियों को एक समूह में समूहित करना चाहिए (भले ही तालिका में कोई पंक्तियाँ न हों - यह अभी भी 0 पंक्तियों का एक समूह है) और 1 पंक्ति लौटाएँ। HAVINGसाथ Trueशर्त यह है कि के बाद सब पर कोई प्रभाव नहीं होना चाहिए।


एक अलग कोण से, इस वापसी की तरह एक प्रश्न में कितनी पंक्तियाँ होनी चाहिए?

SELECT COUNT(*), MAX(b) FROM r;

एक, शून्य या "शून्य या एक, यह निर्भर करता है कि टेबल खाली है या नहीं"?

मुझे लगता है कि एक पंक्ति, चाहे कितनी भी पंक्तियाँ हों r


खैर मुख्य मुद्दा यह है कि क्या यह वास्तव में सच है कि "भले ही तालिका में कोई पंक्तियाँ न हों, फिर भी यह 0 पंक्तियों का एक समूह है"। और मानक इस बारे में स्पष्ट हो जाता है: "यदि कोई समूहीकरण स्तंभ नहीं हैं, तो ... समूहबद्ध तालिका है जिसमें टी केवल इसका एकमात्र समूह है"। (और वह धारण करता है भले ही टी खाली है - इसलिए वास्तव में एक समूह है।) इसके अलावा, होने पर यह निर्दिष्ट करता है कि यह शर्त प्रत्येक समूह पर लागू होती है (उदाहरण में एक बार)। उन्होंने संभवतः इसे इस तरह परिभाषित किया कि SUM और COUNT को खाली T के लिए भी एक पंक्ति में लौटाया जाए।
इरविन स्मौट

+1 (पहले!) भले ही आपके तर्क केविन के रूप में एक ही हो लेकिन मैंने उनके जवाब को कल्पना से उद्धरण के कारण स्वीकार कर लिया है। धन्यवाद!
मार्टिन स्मिथ

@MartinSmith। Thnx। कि मैं आलसी होने से मिलता हूं :)
ypercube

@ypercube: +1 मुझसे भी। मैंने यह साबित करने के लिए अतिरिक्त समय लेने का फैसला किया कि यह साबित करने के लिए कि कहीं कोई वीज़ेल शब्द तो नहीं छिपा है जो आपके उत्तर को गलत बना देगा। लेकिन एक बार मैंने ऐसा किया, तो मैं इसे एक पूर्ण उत्तर के रूप में पोस्ट कर सकता हूं। तो मैंने किया।
केविन कैथार्ट

3
@ErwinSmout: बिल्कुल नहीं। हालाँकि यह अमेरिकी कॉपीराइट कानून के तहत उचित उपयोग के अंतर्गत आता है। शैक्षिक उद्देश्यों के लिए काम के विश्लेषण (यानी आलोचना) के संदर्भ में उद्धृत अपेक्षाकृत छोटे हिस्से, काम की बिक्री की क्षमता पर नगण्य प्रभाव के साथ।
केविन कैथार्ट

3

मैं जो देखता हूं, उससे ऐसा लगता है कि SQLServer और PostgerSQL तालिका में देखने की जहमत नहीं उठाते:

CREATE TABLE r (b INT);
insert into r(b) values (1);
insert into r(b) values (2);
SELECT 1 FROM r HAVING 1=1;

भी सिर्फ एक पंक्ति देता है। हालांकि SQLServer डॉक्स का कहना है

जब ग्रुप BY का उपयोग नहीं किया जाता है, तो HAVING WHERE क्लॉज की तरह व्यवहार करता है।

इस मामले में यह सही नहीं है - WHERE 1=1बदले में HAVINGउचित संख्या में पंक्तियाँ। मैं कहूंगा कि यह आशावादी बग (या कम से कम प्रलेखन बग) है ... SQLServer योजना ' HAVINGऔर' के लिए 'टेबल स्कैन' के मामले में 'लगातार स्कैन' दिखाता है WHERE...

ओरेकल और मैसूरल व्यवहार मुझे अधिक तार्किक और सही लगता है ...


1
आप सही हैं कि SQL सर्वर मेज पर नहीं दिखता है। निष्पादन योजना में केवल एक निरंतर स्कैन होता है और तालिका को संदर्भित भी नहीं करता है। यदि यह केवल SQL सर्वर था, तो मैंने इसे एक बग में डाल दिया था, लेकिन जैसा कि यह कुछ वास्तविक अस्पष्टता है अगर मैं सिर्फ SQL सर्वर नहीं सोच रहा हूं।
मार्टिन स्मिथ

PostgreSQL SQLServer के समान परिणाम दिखाता है, और जहाँ तक मैं explain"परिणाम" (पंक्तियाँ = 1) ... के आउटपुट से बता सकता हूँ कि "WHERE" के लिए और "Seq स्कैन" यह भी तालिका में नहीं दिखता है। .. मुझे लगता है कि यह किसी भी तरह से इस तथ्य से संबंधित है कि "FROM" TSQL और PostgreSQL में अनिवार्य नहीं है। मुझे पता है कि मैसकल को भी इसकी आवश्यकता नहीं है, लेकिन जब से वे समर्थन करते हैं dual, वे शायद क्वेरी को थोड़ा अलग करते हैं। मैं सहमत हूं, यह एक अटकल की तरह लगता है, लेकिन मुझे आशा है कि यह कुछ समझ में आता है।
18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.