2012-03-15 8 views
7

मैंने ओरेकल 11 में पूर्ण आउटर जॉइन का एक अजीब व्यवहार देखा है। मैं मानव संसाधन स्कीमा, विशेष रूप से कर्मचारियों और विभागों से तालिकाओं में शामिल हो रहा था।ओरेकल में पूर्ण बाहरी शामिल होने का अजीब व्यवहार - इसे कैसे समझाया जा सकता है?

उदाहरण के लिए, निम्न क्वेरी 123 पंक्तियों रिटर्न:

SELECT * FROM employees e 
    FULL JOIN departments d ON e.department_id = d.department_id 

हालांकि, समझने के लिए मुश्किल है - जब मैं चयन खंड में विशेष कॉलम का समूह शब्दों में कहें, क्वेरी 122 पंक्तियों वापस आ जाएगी (क लापता पंक्ति एक कर्मचारी जो कोई विभाग सौंपा गया है के लिए है - एक जो अतिरिक्त बाईं के साथ वापस आ गया है भीतरी में शामिल होने की तुलना में शामिल होने):

SELECT first_name, last_name, department_name FROM employees e 
    FULL JOIN departments d on e.department_id = d.department_id 

यहां तक ​​कि जब मैं पंक्तियों गिनती यह रिटर्न 122 (COUNT(*)) !!! क्या हो रहा है? SELECT * और SELECT COUNT(*) के बीच क्या अंतर है?

SELECT * ... के लिए योजना की व्याख्या:

SELECT STATEMENT          122 
    VIEW     VW_FOJ_0      122 
    HASH JOIN       FULL OUTER  122 
     Access Predicates 
     E.DEPARTMENT_ID = D.DEPARTMENT_ID 
     TABLE ACCESS  DEPARTMENTS  FULL   27 
     TABLE ACCESS  EMPLOYEES  FULL   107 

और SELECT COUNT(*) ... के लिए:

SELECT STATEMENT            1 
    SORT          AGGREGATE   1 
    VIEW    VW_FOJ_0       122 
     HASH JOIN       FULL OUTER  122 
     Access Predicates 
      E.DEPARTMENT_ID = D.DEPARTMENT_ID 
     INDEX   DEPT_ID_PK   FAST FULL SCAN 27 
     INDEX   EMP_DEPARTMENT_IX FAST FULL SCAN 107 
+2

क्या होता है ? 'यूनियन ऑल' का उपयोग करते समय कुछ अलग करें?यदि आप 'first_name, last_name, department_name' द्वारा समूह के साथ गिनती करते हैं तो क्या मिलता है? –

+0

'से चुनें * कर्मचारियों से पूर्ण ई-विभाग विभागों पर e.department_id = d.department_id' 123 पंक्तियां और' से चयन गिनती (*) कर्मचारियों से ई और पूर्ण जॉइन विभागों को e.department_id = d.department_id' पर 122 पंक्तियां देता है? –

+0

हां, बिल्कुल - यही कारण है कि मैंने यह प्रश्न पोस्ट किया है। –

उत्तर

5

अनुकूलक का चयन नहीं करने दिया जाना चाहिए करने के लिए

select first_name, last_name, department_name 

और

select count(*) 

विपक्ष में होने की स्थिति में इस कार्य योजना लागू करके चुनें समझाया जाना चाहिए दूसरी क्वेरी में EMP.DEPT_ID पर अनुक्रमणिका का उपयोग करें, क्योंकि इसमें शून्य मान हो सकते हैं। यही कारण है कि यह परिणामों से एक पंक्ति को बाहर करने के लिए कारण बन रहा है।

इस समय के बारे में सोचने वाला एकमात्र गैर-बग स्पष्टीकरण यह है कि आपने किसी भी तरह से अक्षम तरीके से बाधा उत्पन्न की है ताकि अनुकूलक सोच सके कि फ़ील्ड में न्यूल शामिल नहीं हो सकते हैं। इस मामले में बाधाओं में गलत जानकारी दी गई इंडेक्स का उपयोग करना सही होगा। हालांकि, ऐसा लगता है कि रिली विकल्प नल बाधाओं के लिए उपलब्ध नहीं है, इसलिए मुझे नहीं पता कि यह समस्या कैसे हो सकती है। फिर भी, टेबल पर सभी बाधाओं पर सावधानीपूर्वक नजर डालें।

इसके अलावा, ओरेकल की साइट पर पूर्ण बाहरी जुड़ने से गलत परिणामों के बारे में आश्चर्यजनक संख्या में बग हैं। आप उनमें से एक को मार रहे हो सकता है। "मूल" पूर्ण बाहरी मिलती है इन मामलों में से काफी कुछ में, वैकल्पिक हल निष्क्रिय करने के लिए है, जो आप इस कथन से अपने वर्तमान सत्र के लिए कर सकते हैं: अगर आप उन स्तंभों के लिए `union` का उपयोग

alter session set "_optimizer_native_full_outer_join"=off; 
+0

+1: यह सबसे व्यावहारिक स्पष्टीकरण की तरह दिखता है। डीबी संस्करण को जानना दिलचस्प होगा। –

1

(एक टिप्पणी में यह लिखा नहीं जा सकता)

परिणाम निष्पादन की योजना के अनुसार चलाया जाता है।

गिनती (*) निष्पादन योजना इंडेक्स EMP_DEPARTMENT_IX का उपयोग करती है जिसमें नियोक्ता तालिका से सभी dept_ids शामिल होते हैं। लेकिन इंडेक्स में नल नहीं है। तो, यह निष्पादन योजना शून्य विभाग_आईडी के साथ emps "खो" जाएगी।

हालांकि, क्यों ओरेकल

select * 
+1

हां, मैं सहमत हूं। हालांकि यह मेरी राय में एक तरह का असंगतता है। पूर्ण बाहरी जुड़ाव काम नहीं करता है क्योंकि इसे चुनने के अलावा सभी मामलों में होना चाहिए *। –

+0

@ लकीजाका क्या आप 'चयन emp_id' के साथ अधिक परीक्षण कर सकते हैं,' first_name' का चयन करें, 'e.department_id' का चयन करें,' d.department_id' का चयन करें, 'd.department_name' चुनें, आदि? –

+0

हे ... मैंने आपके द्वारा सुझाए गए परीक्षण किए हैं। फिर भी, उनमें से सभी 122 पंक्तियां लौट आए - 123 पंक्तियां प्राप्त करने का एकमात्र तरीका एस्टेरिक्स द्वारा सभी कॉलम का चयन कर रहा है। हालांकि, आखिरकार मैंने संकेतों का उपयोग करके 123 पंक्तियां वापस करने में कामयाब रहे हैं: '/ * + no_index (e) * /'। सभी प्रश्नों को काम करने के लिए पर्याप्त है - या तो 'COUNT (*)' या 'first_name, last_name, department_name'। –

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