बाएं टेबल में एक LEFT OUTER JOIN अधिक रिकॉर्ड कैसे लौटा सकता है?


165

मेरे पास एक बहुत ही मूल LEFT OUTER JOIN है, जो बाईं तालिका से सभी परिणाम और कुछ बड़ी तालिका से कुछ अतिरिक्त जानकारी वापस करने के लिए है। बाईं तालिका में 4935 रिकॉर्ड हैं, फिर भी जब मैं एक अतिरिक्त तालिका में शामिल होता हूं तो रिकॉर्ड संख्या काफी बड़ी हो जाती है।

जहां तक ​​मुझे पता है कि यह पूर्ण सुसमाचार है कि एक बाईं ओर जॉय बाईं तालिका से सभी अभिलेखों को दाएं तालिका से मिलान किए गए रिकॉर्ड के साथ वापस कर देगा और किसी भी पंक्तियों के लिए शून्य मान मेल नहीं खा सकता है, जैसे कि यह मेरी समझ है कि यह होना चाहिए बाईं तालिका में मौजूद से अधिक पंक्तियों को वापस करना असंभव है, लेकिन यह सब एक ही हो रहा है!

SQL क्वेरी निम्नानुसार है:

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

शायद मैंने वाक्य रचना में गलती की है या LEFT OUTER JOIN की मेरी समझ अधूरी है, उम्मीद है कि कोई समझा सकता है कि यह कैसे हो सकता है?

परिशिष्ट भाग

महान जवाब के लिए धन्यवाद, बायाँ ओटीपी जॉन्स की मेरी समझ अब बहुत बेहतर है, लेकिन क्या कोई ऐसा तरीका सुझा सकता है जिससे इस प्रश्न को संशोधित किया जा सके ताकि मैं केवल उतने ही रिकॉर्ड प्राप्त कर सकूं जितना कि बाईं तालिका में मौजूद है?

यह क्वेरी विशुद्ध रूप से एक रिपोर्ट उत्पन्न करने के लिए है और डुप्लिकेट मैच केवल मामलों को भ्रमित करते हैं।

/परिशिष्ट भाग


5
"बाएं तालिका में मौजूद के रूप में कई रिकॉर्ड लौटाए जाने के लिए", आपको यह निर्दिष्ट करने की आवश्यकता है कि एकाधिक मिलान होने पर चुनने के लिए दाईं ओर से कौन सी पंक्ति है।
एके

1
आप इसे कैसे निर्दिष्ट करते हैं? मैं पहला मैच लौटना चाहूंगा।
साइमन क्रॉस

1
आपको परिभाषित करना होगा कि पहले मैच का क्या मतलब है। क्या आप जल्द से जल्द रिकॉर्ड चाहते हैं, उच्चतम आईडी के साथ या क्या?
HLGEM

1
यदि आप अतिरिक्त तालिका में प्राथमिक कुंजी के साथ मेल खाते हैं तो आपका कथन सही है।
प्रागेथ गॉडेज

मैं अक्सर इस तरह के एक संसाधन का उपयोग करता हूं जब एक प्रश्न पत्र का निर्माण होता है। यदि लिंक कभी मर जाता है, तो बस Google sql जुड़ता है ; वे विभिन्न प्रकार के जुड़ने के वेन आरेख हैं।
झिमनो

जवाबों:


190

बायाँ ओपिन जॉय जहाँ संभव हो वहाँ दायाँ तालिका के साथ शामिल होने वाले बाएँ तालिका से सभी रिकॉर्ड लौटाएगा।

यदि मैच होते हैं, तो यह अभी भी मैच वाली सभी पंक्तियों को वापस कर देगा, इसलिए, LEFT में एक पंक्ति जो RIGHT में दो पंक्तियों से मेल खाती है, एक INNER JOIN की तरह ही दो ROWS के रूप में वापस आएगी।

संपादित करें: आपके संपादन के जवाब में, मैंने अभी आपकी क्वेरी पर एक और नज़र डाली है और ऐसा लगता है कि आप केवल LEFT तालिका से डेटा लौटा रहे हैं। इसलिए, यदि आप केवल LEFT तालिका से डेटा चाहते हैं, और आप केवल LEFT तालिका में प्रत्येक पंक्ति के लिए एक पंक्ति लौटना चाहते हैं, तो आपको बिल्कुल एक JOIN करने की कोई आवश्यकता नहीं है और केवल LEFT तालिका से सीधे चयन कर सकते हैं।


1
सही तालिका में शामिल होने का कारण इसलिए मुझे केवल बाएं से रिकॉर्ड मिला, जहां सही तालिका में कम से कम एक रिकॉर्ड था, लेकिन स्पष्टीकरण के लिए बहुत-बहुत धन्यवाद।
जय वाइल्ड


39

यह असंभव नहीं है। बाईं तालिका में रिकॉर्ड की संख्या न्यूनतम रिकॉर्ड है जिसे वह वापस करेगा। यदि सही तालिका में दो रिकॉर्ड हैं जो बाईं तालिका में एक रिकॉर्ड से मेल खाते हैं, तो यह दो रिकॉर्ड लौटाएगा।


12

आपकी पोस्टस्क्रिप्ट के जवाब में, यह इस बात पर निर्भर करता है कि आप क्या चाहते हैं।

आप अपनी बाईं तालिका में प्रत्येक पंक्ति के लिए (संभव) कई पंक्तियाँ प्राप्त कर रहे हैं क्योंकि जुड़ने की स्थिति के लिए कई मिलान हैं। यदि आप चाहते हैं कि आपके कुल परिणाम में उसी तरह की पंक्तियाँ हों, जैसे कि क्वेरी के बाएँ भाग में हैं, तो आपको यह सुनिश्चित करना होगा कि आपकी सम्मिलित स्थितियों के कारण 1-टू -1 मैच हो।

वैकल्पिक रूप से, आप वास्तव में जो चाहते हैं उसके आधार पर आप समग्र कार्यों का उपयोग कर सकते हैं (उदाहरण के लिए यदि आप सही भाग से एक स्ट्रिंग चाहते हैं तो आप एक स्तंभ उत्पन्न कर सकते हैं जो उस बाईं पंक्ति के लिए दाईं ओर परिणाम का एक अल्पविरामांकित स्ट्रिंग है।

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


4
यह एक अच्छा जवाब है क्योंकि इसने सुझाव दिया है कि बाईं तालिका से सिर्फ पंक्तियों को कैसे वापस किया जाए।
मार्स

9

बाईं मेज से प्रत्येक रिकॉर्ड को कई बार वापस किया जाएगा क्योंकि दाएं टेबल पर मिलान रिकॉर्ड हैं - कम से कम 1, लेकिन आसानी से 1 से अधिक हो सकता है।


8

बाईं ओर जिन्न की तरह इनर जॉय (सामान्य जुड़ाव) बाईं तालिका में प्रत्येक पंक्ति के लिए कई परिणाम के रूप में वापस आ जाएगा, क्योंकि यह सही तालिका में कई मैचों में मिलता है। इसलिए आपके पास बहुत सारे परिणाम हो सकते हैं - एन एक्स एम तक, जहां एन लेफ्ट टेबल में पंक्तियों की संख्या है और एम राइट टेबल में पंक्तियों की संख्या है।

यह हमेशा कम से कम एन होने के लिए LEFT OUTER JOIN में न्यूनतम परिणाम की गारंटी है।


1
मैंने सोचना शुरू किया कि पंक्तियों की संख्या N N M के बराबर है और केवल वास्तविक स्थिति जो मेरे दिमाग में आती है जब N या M बराबर होती है। 1. क्या आप सहमत हैं?
बार्टोज़ज़मिलर

2
नहीं, मैं नहीं। आपको शर्त में शामिल होने के बारे में नहीं सोचना चाहिए क्योंकि प्रमुख समानता केवल शामिल होती है। यह मनमानी स्थिति हो सकती है, उदाहरण के लिए तिथि सीमाएँ, असमानताएं, दो चरम मामले: (ए) एन पंक्तियों में एम पंक्तियों के बीच एक भी मैच नहीं है, फिर एन पंक्तियों में बाहरी जुड़ने वाले परिणामों को NULLs के साथ मिलान किया गया। (b) प्रत्येक N पंक्तियाँ सभी M पंक्तियों से मेल खाती हैं, तो परिणाम N x M पंक्तियाँ सेट होती हैं।
टॉपचेफ़

1
आप सही हैं, मैं केवल प्रमुख समानता के संदर्भ में जुड़ने के बारे में सोच रहा था। मुझे "केस बी" से आपका उदाहरण पसंद है। मेरा मानना ​​है कि "हर एन पंक्तियाँ सभी एम पंक्तियों से मेल खाती हैं" एन एक्स एम पंक्तियों के वापस आने के लिए एक सामान्य नुस्खा है, जो केवल महत्वपूर्ण समानता के बारे में सोचते समय कल्पना करना असंभव है।
बार्टोज़ज़मिलर


6

ध्यान दें कि यदि आपके पास बाईं ओर बाहरी क्वेरी से युक्त क्वेरी के "दाईं ओर" तालिका में एक खंड है, तो ... यदि आपके पास दाईं ओर कोई रिकॉर्ड नहीं है, जहां खंड को संतुष्ट करता है, तो 'बाईं ओर' का संगत रिकॉर्ड 'आपकी क्वेरी के परिणाम में तालिका नहीं दिखाई देगी ...।


1
फिर आपको इसी लेफ्ट OUTER JOIN के ON क्लॉज में कंडीशन जोड़ना चाहिए।
मिक

6

यदि आपको दाईं ओर से किसी एक पंक्ति की आवश्यकता है

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

या केवल

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)

1
क्योंकि आपने डीडीएल और डीएमएल प्रदान नहीं किया, मैंने परीक्षण नहीं किया। वैसे भी मुझे लगता है कि EXISTS वही है जो आप चाहते हैं। इसे आज़माएं: सस्पेक्टेनरीस, साइटिड फॉरम (SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER) () OVER (पार्टी द्वारा शेयर) SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum पर DATA.Dim_Member को शामिल करें, जहां t = rn = 1
AK

2

ऐसा लगता है जैसे DATA.Dim_Member टेबल प्रति SUSP.Susp_Visits पंक्ति में कई पंक्तियाँ हैं।


2

यदि Dim_Member में एकाधिक (x) पंक्तियाँ Susp_Visits में एकल पंक्ति से संबद्ध हैं, तो resul सेट में x पंक्तियाँ होंगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.