2012-03-28 10 views
5

मैं ansi-92 SQL मानक सीखने की कोशिश कर रहा हूं, लेकिन मुझे इसे पूरी तरह से समझ में नहीं आता है (मैं ansi-89 मानक के साथ-साथ डेटाबेस में सामान्य रूप से नया हूं)।क्या मैं जॉइन को गलत समझता हूं?

मेरे उदाहरण में, मेरे पास तीन टेबल साम्राज्य हैं - < परिवार - < प्रजातियां (जीवविज्ञान वर्गीकरण)।

  • प्रजातियों और न ही परिवारों के बिना साम्राज्य हो सकते हैं।
  • प्रजातियों के बिना परिवार और न ही दयालु हो सकते हैं।
  • राज्य या परिवार के बिना प्रजातियां हो सकती हैं।

ऐसा क्यों होता है?

एक जीवविज्ञानी, एक नई प्रजाति पाता है लेकिन वह एक राज्य या परिवार में इस वर्गीकृत नहीं किया गया है, एक नए परिवार कोई प्रजातियां पायी जाती हैं और क्या राज्य यह संबंधित होना चाहिए के बारे में निश्चित नहीं है कि बनाता है, आदि

यहाँ

कहो एक बेवकूफ है (अंतिम प्रश्न देखें): http://sqlfiddle.com/#!4/015d1/3

मैं एक प्रश्न बनाना चाहता हूं जो मुझे हर राज्य, हर प्रजाति को वापस लाए, लेकिन उन परिवारों में नहीं, जिनके पास कोई प्रजाति नहीं है, इसलिए मैं इसे बना देता हूं।

select * 
    from reino r 
     left join (
      familia f    
      right join especie e 
       on f.fnombre = e.efamilia 
       and f.freino = e.ereino 
     ) on r.rnombre = f.freino 
      and r.rnombre = e.ereino; 

मैं क्या लगता है कि यह करना होगा है:

  1. एक अधिकार के रूप में परिवार और प्रजातियों में शामिल होने के शामिल हो, तो यह हर प्रजाति लाता है, लेकिन नहीं उन परिवारों कोई प्रजाति है। इसलिए, यदि एक प्रजाति को किसी परिवार में वर्गीकृत नहीं किया गया है, तो यह परिवार पर शून्य के साथ दिखाई देगा।

  2. फिर, बाएं शामिल होने के परिणामस्वरूप राज्य में शामिल हों, इसलिए यह हर राज्य को लाता है, भले ही उस राज्य पर कोई परिवार या प्रजातियां वर्गीकृत न हों।

क्या मैं गलत हूँ? क्या यह मुझे उन प्रजातियों को नहीं दिखाया जाना चाहिए जिन्हें वर्गीकृत नहीं किया गया है? अगर मैं आंतरिक पूछताछ करता हूं तो यह मुझे जो चाहिए वह लाता है। क्या कोई समस्या है जहां मैं चीजों को समूहीकृत कर रहा हूं?

+0

इस क्वेरी अनुकूलन कि ओरेकल करता है ?, अपनी क्वेरी में गड़बड़ी न करता, कोष्ठक अनावश्यक हैं? क्या मुझे एक ही परिणाम मिल रहा है? आदेश ऑरैकल निर्देश क्या है? – Roger

+0

@outis मुझे सम्मान से असहमत होना है कि वाक्यविन्यास में शामिल होना घोंसला नहीं है। [मेरा मानना ​​है कि यह आलेख इस विषय पर चर्चा करता है] (http://tonyhasler.wordpress.com/2009/02/22/parentheses-in-ansi-join-syntax/) और निष्कर्ष निकाला है कि आदेश के स्पष्टीकरण के लिए ब्रांड्स का उपयोग किया जा सकता है कई तालिकाओं में शामिल होने पर संचालन। –

+0

@ माइकलफ्रेड्रिकसन: मैं सही खड़ा हूं। वहां है, एसक्यूएल/फाउंडेशन § 7.6। – outis

उत्तर

2

आप # 1 के विवरण पर सही हैं ... आपकी क्वेरी के साथ समस्या चरण # 2 पर है।

जब आप करने के लिए (परिवार & प्रजाति), तो आप हर राज्य का अनुरोध कर रहे हैं, वहाँ कोई मिलता-जुलता है, भले ही (परिवार & प्रजाति) राज्य से एक left join कर ... फिर भी, यह आप नहीं लौटेगा किसी भी (परिवार & प्रजातियां) संयोजन जिसमें मिलान करने वाला साम्राज्य नहीं है।

करीब क्वेरी होगा:

select * 
    from reino r 
     full join (
      familia f    
      right join especie e 
       on f.fnombre = e.efamilia 
       and f.freino = e.ereino 
     ) on r.rnombre = f.freino 
      and r.rnombre = e.ereino; 

सूचना है कि left join एक full join के साथ बदल दिया गया था ...

हालांकि, यह केवल परिवारों से जुड़े परिवारों को लौटाता है ... यह किसी भी परिवार को वापस नहीं लौटाता है जो कि साम्राज्यों से जुड़ा हुआ है लेकिन प्रजातियां नहीं।

अपने प्रश्न को फिर से पढ़ने के बाद, यह वास्तव में है आप चाहते थे चाहते हैं ...


संपादित करें: आगे सोचा पर, आप हो सकता है आपकी क्वेरी इसलिए की तरह फिर से लिखें:

select * 
from 
    especie e 
    left join familia f 
     on f.fnombre = e.efamilia 
     and f.freino = e.ereino 
    full join reino r 
     on r.rnombre = f.freino 
     and r.rnombre = e.ereino; 

मुझे लगता है कि यह प्राथमिक होगा, क्योंकि आप RIGHT JOIN को खत्म करते हैं, जो आम तौर पर खराब शैली के लिए तैयार होते हैं ... और ब्रांड्स, जो लोगों के लिए सही ढंग से विश्लेषण करने के लिए मुश्किल हो सकता है यह निर्धारित करने के लिए कि परिणाम क्या होगा।

+0

बहुत बहुत धन्यवाद, अब चीजें स्पष्ट हैं। समय लेने के लिए धन्यवाद :) – Roger

+0

हालांकि सिर्फ एक और सवाल; आउटिस से किए गए मेरे प्रश्न पर टिप्पणी पढ़ें। क्या ब्रांड्स अनावश्यक हैं? क्या यह ओरेकल अनुकूलक के साथ गड़बड़ करता है? – Roger

+0

मैं @outis से असहमत हूं ... लेकिन मैं मुख्य रूप से SQL सर्वर में काम करता हूं इसलिए यह ओरेकल में भिन्न हो सकता है। हालांकि, मेरे अनुभव में, कोष्ठक दोनों परिणामों के साथ-साथ निष्पादन योजना को भी प्रभावित कर सकता है। [यहां एक स्रोत है जो मेरा मानना ​​है कि ओरेकल में इसकी पुष्टि करता है।] (Http://tonyhasler.wordpress.com/2009/02/22/parentheses-in-ansi-join-syntax/) ...मुझे यकीन नहीं है कि आप ब्रांड्स का उपयोग किए बिना उस क्वेरी को पुन: स्थापित कैसे करेंगे (आपको शायद इसे उप-चयन में बदलना होगा), लेकिन यदि आप कर सकते हैं, तो आप यह सुनिश्चित करने के लिए दो दृष्टिकोणों के बीच निष्पादन योजनाओं की तुलना कर सकते हैं। आपका मूल दृष्टिकोण स्वीकार्य है। –

0

इस का उपयोग करने का प्रयास करें:

select * 
from reino r 
join especie e on (r.rnombre = e.ereino) 
join familia f on (f.freino = e.ereino and f.fnombre = e.efamilia) 

यह हो सकता है, कि तुम मेज especie में efamilia और enombre अदला-बदली?

+0

मैं भीतरी जॉइन की तलाश नहीं कर रहा हूं, वैसे भी धन्यवाद। – Roger

2

मामले में यह मदद करता है:

संबंधित रूप से कहा जाए तो बन्दूक शादी का एक प्रकार [OUTER JOIN है]: का एक प्रकार में यह बलों टेबल संघ-हाँ, मेरा मतलब है संघ है, में शामिल होने के-भी नहीं जब प्रश्न की तालिका यूनियन के लिए सामान्य आवश्यकताओं के अनुरूप होने में असफल हो जाती है। यह वास्तव में, एक या को संघ बनाने से पहले नल के साथ दोनों तालिकाओं को पैडिंग करके करता है, जिससे उन्हें सभी सामान्य आवश्यकताओं के अनुरूप बना देता है। लेकिन इस उदाहरण के रूप में कोई कारण है कि कि गद्दी बजाय nulls के उचित मूल्यों के साथ नहीं किया जाना चाहिए है,:

SELECT SNO , COALESCE (PNO , 'nil') AS PNO 
FROM S NATURAL LEFT OUTER JOIN SP 

स्रोत:

SELECT SNO , PNO 
FROM SP 
UNION 
SELECT SNO , 'nil' AS PNO 
FROM S 
WHERE SNO NOT IN (SELECT SNO FROM SP) 

ऊपर के बराबर है: SQL and Relational Theory: How to Write Accurate SQL Code By C. J. Date

1

यदि आप चाहते हैं कि क्वेरी आपके पास जो कुछ है, उससे केवल थोड़ी सी बदलाव के साथ पुनः लिखा जाए, तो आपबदल सकते हैंFULL में शामिल हों। आप आगे बेमानी कोष्ठक और r.rnombre = f.freinoON हालत से निकाल सकते हैं:

select * 
from reino r 
    full join      --- instead of LEFT JOIN 
     familia f    
     right join especie e 
      on f.fnombre = e.efamilia 
      and f.freino = e.ereino 
     on r.rnombre = e.ereino; 
           ---removed the: r.rnombre = f.freino  
+0

मुझे सबसे अच्छा परिणाम चाहिए, मुझे परवाह नहीं है कि मुझे इसे फिर से लिखना है; डेटाबेस के लिए सबसे अच्छा क्या है और क्यों? – Roger

+0

चूंकि आप केवल प्रजातियों वाले परिवार चाहते हैं, 'r.rnombre = f.freino' की आवश्यकता नहीं है। डीबीएमएस के आधार पर जुड़ें संरचना से ब्रांड्स को हटाकर कोई प्रभाव नहीं पड़ सकता है (और उस बिंदु पर ओरेकल में कोई विशेषज्ञ नहीं है)। –

+0

बस एक नाबालिग नहीं। यह प्रश्न (और स्वीकार किए गए एक, माइकल द्वारा) उन परिवारों को शामिल नहीं करेगा जिनमें साम्राज्य हैं (लेकिन प्रजातियां नहीं हैं)। –

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