2013-12-16 11 views
8

दो तालिकाओं मान लें:सबक्वायरी में WHERE स्थिति मुख्य क्वेरी को प्रभावित करती है - क्या यह एक सुविधा या बग है?

Table A: A1, A2, A_Other 
Table B: B1, B2, B_Other 

निम्न उदाहरणों में,is somethingएक शर्त एक निश्चित मान, उदा के खिलाफ जाँच की है= 'ABC'या< 45

Select * from A 
Where A1 IN (
    Select Distinct B1 from B 
    Where B2 is something 
    And A2 is something 
); 

क्या मैं सच में था (2) लिखने का मतलब:

Select * from A 
Where A1 IN (
    Select Distinct B1 from B 
    Where B2 is something 
) 
And A2 is something; 

अजीब, दोनों प्रश्नों

मैं जैसे निम्नलिखित (1) एक प्रश्न लिखा था एक ही परिणाम लौटा दिया। जब को देख क्वेरी की योजना समझाने, यह, जैसे जब सबक्वेरी मार डाला गया था देखा क्योंकि हालत A2 is something सबक्वेरी के लिए लागू नहीं था, यह मुख्य क्वेरी परिणामों पर एक फिल्टर के रूप में उपयोग के लिए आस्थगित था।

मैं सामान्य रूप से उम्मीद करेंगे क्वेरी विफल क्योंकि सबक्वेरी ही से विफल हो जाएगा:

Select Distinct B1 from B 
Where B2 is something 
And A2 is something; --- ERROR: column "A2" does not exist 

लेकिन मैं पाते हैं कि ऐसा नहीं है, और Postgres मुख्य क्वेरी के लिए अयोग्य सबक्वेरी की स्थिति defers ।

क्या यह मानक व्यवहार या पोस्टग्रेस विसंगति है? यह दस्तावेज कहां है, और यह सुविधा क्या कहा जाता है?

इसके अलावा, मुझे लगता है कि अगर मैं मेज B में एक स्तंभ A2 जोड़ने के लिए, के रूप में मूल रूप से करना ही क्वेरी काम करता है लगता है। इस मामले में क्वेरी में संदर्भ A2 अभी भी A.A2 को उल्लेख करता है, लेकिन क्वेरी में संदर्भ नया स्तंभ B.A2 को उल्लेख करता है, क्योंकि यह सबक्वेरी में सीधे अब लागू है।

+2

यह एक सहसंबंधित सबक्वायरी है। – OldProgrammer

+0

यह ठीक प्रतीत नहीं होता है क्योंकि मैं subquery में परिणाम फ़िल्टर करने के लिए मुख्य क्वेरी में मानों का उपयोग कर _really_ नहीं कर रहा हूं (जो सहसंबंधित सबक्वायरी करता है)। यहां फ़िल्टर मुख्य क्वेरी पर अभी भी लागू है। लेकिन हाँ, यह हो सकता है। _Btw, यह बताते हुए एक विस्तृत उत्तर अच्छा होगा कि क्या हो रहा है ._ – ADTC

+0

ए 2 कुछ है या बी 2 कुछ स्पष्ट नहीं है। यह उस पर निर्भर करता है। मुझे लगता है कि कुछ रिकॉर्ड के आधार पर आप दोनों क्वेरी से एक ही परिणाम प्राप्त कर रहे हैं। – KumarHarsh

उत्तर

5

यहां बहुत बढ़िया सवाल है, जो कुछ लोग आते हैं लेकिन रोकने और देखने के लिए परेशान नहीं हैं।

आप क्या कर रहे हैं WHERE खंड में एक सबक्वायरी लिख रहा है; FROM खंड में एक इनलाइन व्यू नहीं। अंतर है

जब आप SELECT या WHERE क्लॉज में एक सबक्वायरी लिखते हैं, तो आप मुख्य क्वेरी के FROM खंड में मौजूद तालिकाओं तक पहुंच सकते हैं। यह केवल पोस्टग्रेस में नहीं होता है, लेकिन यह एक मानक व्यवहार है और ओरेकल, एसक्यूएल सर्वर और माईएसक्यूएल सहित सभी प्रमुख आरडीबीएमएस में देखा जा सकता है।

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

यदि आप केवल मुख्य क्वेरी को टिप्पणी करते हुए सबक्वायरी चलाते हैं, तो उस स्थिति में एक त्रुटि वापस करने के लिए बाध्य है जिसे आपने उल्लिखित कॉलम के रूप में वर्णित किया है।

अपने अंतिम अनुच्छेद में, आपने उल्लेख किया है कि आपने तालिका पर एक कॉलम A2 जोड़ा है। आपने जो देखा है वह सही है। यह अंतर्निहित संदर्भ घटना के कारण होता है। यदि आप कॉलम के लिए तालिका उपनाम का उल्लेख नहीं करते हैं, तो डेटाबेस इंजन उपरोक्त के FROM खंड में तालिका में कॉलम को पहले देखता है। केवल अगर कॉलम नहीं मिला है, तो मुख्य क्वेरी में तालिकाओं में एक संदर्भ दिया जाता है। आप निम्न क्वेरी का उपयोग करते हैं, यह अभी भी एक ही परिणाम वापसी होगी:

Select * from A aa -- Check the alias 
Where A1 IN (
    Select Distinct B1 from B bb 
    Where B2 is something 
    And aa.A2 is something -- Check the reference 
); 

शायद आप संबंधपरक डाटाबेस पर Korth की पुस्तक में अधिक जानकारी प्राप्त कर सकते हैं, लेकिन मुझे यकीन है कि नहीं हूँ। मैंने अपने अवलोकनों के आधार पर अभी आपके प्रश्न का उत्तर दिया है। मुझे पता है यह होता है और क्यों। मुझे नहीं पता कि मैं आपको और संदर्भ कैसे प्रदान कर सकता हूं।

2

सहसंबंधित सबक्वायरी: - यदि उपकुंजी का परिणाम इसकी मूल क्वेरी तालिका के कॉलम के मान पर निर्भर करता है तो उप क्वेरी को सहसंबंधित सबक्वायरी कहा जाता है। यह मानक व्यवहार है, त्रुटि नहीं।

यह आवश्यक नहीं है कि जिस कॉलर पर सहसंबंधित क्वेरी निर्भर है, वह मूल क्वेरी की चयनित कॉलम सूची में शामिल है।

Select * from A 
Where A1 IN (
    Select Distinct B1 from B 
    Where B2 is something 
    And A2 is something 
); 

ए 2 टेबल एक का एक स्तंभ है और माता पिता क्वेरी तालिका ए इसका मतलब है कि ए 2 सबक्वेरी में संदर्भित किया जा सकता पर है। उपर्युक्त क्वेरी निम्न की तुलना में धीमी गति से काम कर सकती है।

Select * from A 
Where A2 is something And A1 IN (
    Select Distinct B1 from B 
    Where B2 is something 
); 

ऐसा इसलिए है क्योंकि पैरेंट क्वेरी से ए 2 को लूप में संदर्भित किया जाता है। यह डेटा प्राप्त करने की स्थिति पर निर्भर करता है। यदि सबक्वायरी

Select Distinct B1 from B 
Where B2 is A2 

जैसे कुछ है तो हमें मूल क्वेरी कॉलम का संदर्भ देना होगा। वैकल्पिक रूप से, हम जुड़ने का उपयोग कर सकते हैं।

2

आपके पास पहले से ही यह स्पष्टीकरण है कि WHERE खंड में सहसंबंधित सबक्वायरी FROM सूची में तालिकाओं से सभी कॉलम का संदर्भ दे सकते हैं।

कि से

के अलावा, एक JOIN या एक EXISTS अर्द्ध में शामिल होने का उपयोग कर अक्सर काफी तेजी से सहसंबद्ध सबक्वेरी से है। मैं इस 100% बराबर प्रश्न के पुनर्लेखन होगा:

SELECT a.* 
FROM a 
JOIN (
    SELECT DISTINCT b1 
    FROM b 
    WHERE b2 is something 
    ) b ON b.b1 = a.a1 
WHERE a.a2 is something 

या, बेहतर अभी तक:

SELECT * 
FROM a 
WHERE EXISTS (
    SELECT 1 
    FROM b 
    WHERE b.b1 = a.a1 
    AND b.b2 is something 
    ) 
AND a.a2 is something; 
0

परिणाम अजीब नहीं हैं, सबक्वेरी सकते अभिभावक क्वेरी referernce। इसे एक सहसंबंधित सबक्वियर कहा जाता है और यह बहुत आम है। आपके उदाहरण में आपने आईएन ऑपरेटर का उपयोग किया था, लेकिन आमतौर पर आईएन ऑपरेशन के साथ एक क्वेरी को ऑप्टिमाइज़ करने के लिए एक सहसंबंधित सबक्वियर का उपयोग कर EXISTS ऑपरेटर के साथ IN को प्रतिस्थापित करना है।

एक्स्ट्स के बारे में इरविन की टिप्पणी को विस्तारित करने के लिए विस्तारित करने के लिए, ऐसा इसलिए है क्योंकि जब आप "कभी-कभी" में उपयोग करते हैं तो सेट के सभी मानों को खोजने के लिए क्वेरी की आवश्यकता होती है। जबकि EXISTS का उपयोग करने के लिए बस शर्त को पूरा करने के लिए पहली घटना की आवश्यकता होती है। हालांकि शायद यह मामला है कि क्वेरी प्लान दोनों एक जैसा होने का अनुकूलन करता है। लेकिन EXISTS का उपयोग करके इच्छित क्वेरी योजना को तेजी से बनाने में ऑप्टिमाइज़र की स्पष्ट रूप से सहायता करें।

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