MySQL में FULL OUTER JOIN कैसे करें?


654

मैं MySQL में Full Outer Join करना चाहता हूं। क्या यह संभव है? क्या MySQL द्वारा पूर्ण बाहरी जॉइन सपोर्ट किया गया है?



4
इस सवाल के बेहतर जवाब हैं
जूलियो मैरिंस

यहां उत्तरों से सावधान रहें। SQL मानक कहता है कि फुल ज्वाइन इन रोल्स यूनियन पर इन-ज्वाइन है, सभी बेजोड़ लेफ्ट टेबल रोल्स को nulls यूनियन द्वारा बढ़ाया गया है, सभी राइट टेबल रोल्स nulls द्वारा बढ़ाया गया है। यहां अधिकांश उत्तर गलत हैं (टिप्पणियों को देखें) और जो गलत नहीं हैं वे सामान्य मामले को नहीं संभालते हैं। हालांकि कई (अनुचित) अपवित्र हैं। (मेरा जवाब देखें।)
फिलिप

जब आप गैर-प्राथमिक कुंजी / समूहीकृत स्तंभों द्वारा जुड़ने का प्रयास कर रहे हों, तब क्या होगा? जैसे मेरे पास प्रति राज्य "राज्य", "बेचता है" और प्रति राज्य "राज्य", "व्यय" के अन्य खर्चों की एक क्वेरी है, दोनों प्रश्न समूह ("राज्य") द्वारा समूह का उपयोग करते हैं। जब मैं बाएं और दाएं के बीच संघ में दो प्रश्नों के बीच जुड़ता हूं तो मुझे कुछ पंक्तियां मिलती हैं जो बिकती हैं, लेकिन कोई खर्च नहीं, खर्च के साथ कुछ और लेकिन कोई बेचता नहीं है, सब कुछ इस बिंदु पर सही है, लेकिन मुझे दोनों के साथ कुछ भी मिलता है बेचता है और खर्च और एक दोहराया "राज्य" कॉलम ... बहुत समस्या नहीं है, लेकिन सही नहीं लगता ...
Jairo Lozano

1
@JairoLozano बाधाओं को क्वेरी करने की आवश्यकता नहीं है। यद्यपि जब बाधाएं अतिरिक्त प्रश्न रखती हैं तो वांछित उत्तर वापस कर देती हैं जो अन्यथा नहीं होता। दी गई दलीलों के लिए रिटर्न पर पूर्ण बाधा क्या है, इस पर कोई असर नहीं पड़ता। आपके द्वारा वर्णित समस्या यह है कि आपके द्वारा लिखी गई क्वेरी गलत क्वेरी है। (संभवतः सामान्य त्रुटि जहां लोग कुछ जुड़ाव चाहते हैं, प्रत्येक में संभवतः कुछ अलग-अलग उपकुंजियों की कुंजी शामिल होती है, प्रत्येक संभवत: सम्मिलित और / या एकत्रीकरण में शामिल होती है, लेकिन वे गलत तरीके से सभी जुड़ने की कोशिश करते हैं, फिर सभी समुच्चय या पिछले एकत्रीकरण पर एकत्र करने के लिए। ।)
5

जवाबों:


669

MySQL पर आपके पास पूर्ण जॉन्स नहीं हैं, लेकिन आप निश्चित रूप से उनका अनुकरण कर सकते हैं

आपके लिए इस SO प्रश्न से ट्रांसलेट किए गए एक कोड के लिए :

दो तालिकाओं के साथ t1, t2:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

ऊपर दी गई क्वेरी उन विशेष मामलों के लिए काम करती है जहाँ एक पूर्ण OOO JOIN ऑपरेशन कोई डुप्लिकेट पंक्तियाँ उत्पन्न नहीं करेगा। उपर्युक्त UNIONक्वेरी क्वेरी पैटर्न द्वारा शुरू की गई डुप्लिकेट पंक्तियों को हटाने के लिए सेट ऑपरेटर पर निर्भर करती है । हम दूसरी क्वेरी के लिए एंटी-जॉइन पैटर्न का उपयोग करके डुप्लिकेट पंक्तियों को शुरू करने से बच सकते हैं , और फिर दो सेटों को संयोजित करने के लिए एक UNION ALL सेट ऑपरेटर का उपयोग कर सकते हैं। अधिक सामान्य मामले में, जहां एक पूर्ण OOO JOIN डुप्लिकेट पंक्तियों को लौटाएगा, हम यह कर सकते हैं:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.id IS NULL

33
दरअसल आपके द्वारा लिखी गई बात सही नहीं है। क्योंकि जब आप एक UNION करते हैं तो आप डुप्लिकेट हटा देंगे, और कभी-कभी जब आप दो अलग-अलग तालिकाओं में शामिल होते हैं तो डुप्लिकेट होना चाहिए।
पावले लेसिक

158
यह सही उदाहरण है:(SELECT ... FROM tbl1 LEFT JOIN tbl2 ...) UNION ALL (SELECT ... FROM tbl1 RIGHT JOIN tbl2 ... WHERE tbl1.col IS NULL)
पावले लेसिक

8
इसलिए अंतर यह है कि मैं एक लेफ्ट इन्क्लूसिव जॉइन कर रहा हूं और फिर UNION ALL
Pavle Lekic

5
और मैं देख रहा हूं कि अब आप कहते हैं कि क्षमा करें। शायद आप अपने उत्तर को अपडेट कर सकते हैं, क्योंकि यह मामला है कि यह गलत हो जाता है और यह कि UNION ALL हमेशा अधिक कुशल होने वाला है?
यश

10
@ypercube: यदि कोई डुप्लिकेट पंक्तियाँ नहीं हैं ( t1और t2, तो इस उत्तर में क्वेरी एक परिणाम को लौटाती है जो फुल ऑउटफिट को इम्यूलेट करता है। लेकिन अधिक सामान्य स्थिति में, उदाहरण के लिए, चयनित सूची में लौटी हुई पंक्तियों को अद्वितीय बनाने के लिए पर्याप्त कॉलम / भाव नहीं होते हैं, तो यह क्वेरी पैटर्न उस सेट को पुन: उत्पन्न करने के लिए अपर्याप्त है जिसे एक द्वारा निर्मित किया जाएगा FULL OUTER JOIN। अधिक वफादार अनुकरण प्राप्त करने के लिए, हमें एक UNION ALLसेट ऑपरेटर की आवश्यकता होगी , और प्रश्नों में से एक को एक एंटी-जॉइन पैटर्न की आवश्यकता होगी । Pavle Lekic (ऊपर) की टिप्पणी सही क्वेरी पैटर्न देती है।
spencer7593

350

पाब्लो सांता क्रूज़ ने जो उत्तर दिया वह सही है; हालाँकि, यदि कोई भी इस पृष्ठ पर ठोकर खाई है और अधिक स्पष्टीकरण चाहता है, तो यहाँ एक विस्तृत विराम है।

उदाहरण सारणी

मान लें कि हमारे पास निम्नलिखित तालिकाएँ हैं:

-- t1
id  name
1   Tim
2   Marta

-- t2
id  name
1   Tim
3   Katarina

भीतरी जुड़ता है

एक आंतरिक जुड़ाव, इस तरह:

SELECT *
FROM `t1`
INNER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

क्या हमें केवल दोनों तालिका में दिखाई देने वाले रिकॉर्ड मिलेंगे, जैसे:

1 Tim  1 Tim

इनर जॉइन की एक दिशा नहीं है (जैसे बाएं या दाएं) क्योंकि वे स्पष्ट रूप से द्विदिश हैं - हमें दोनों तरफ मैच की आवश्यकता है।

बाहरी जोड़

दूसरी ओर, बाहरी जोड़ ऐसे रिकॉर्ड खोजने के लिए हैं, जिनका अन्य तालिका में मेल नहीं हो सकता है। इस प्रकार, आपको यह निर्दिष्ट करना होगा कि कौन से पक्ष को लापता रिकॉर्ड रखने की अनुमति है।

LEFT JOINऔर के RIGHT JOINलिए आशुलिपि LEFT OUTER JOINऔर हैं RIGHT OUTER JOIN; बाहरी जोड़ बनाम आंतरिक जोड़ की अवधारणा को सुदृढ़ करने के लिए मैं नीचे उनके पूर्ण नामों का उपयोग करूंगा।

बाईं ओर का बाहरी जोड़

एक बायाँ बाहरी जोड़, इस तरह:

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

... हमें बाईं तालिका से सभी रिकॉर्ड मिलेंगे, भले ही उनके पास सही तालिका में मैच हो या नहीं, इस तरह से:

1 Tim   1    Tim
2 Marta NULL NULL

राइट आउटर जॉइन करें

एक सही बाहरी जुड़ाव, इस तरह:

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

... हमें सही तालिका से सभी रिकॉर्ड मिलेंगे, भले ही उनकी बाईं तालिका में मैच हो या न हो, इस तरह:

1    Tim   1  Tim
NULL NULL  3  Katarina

पूर्ण बाहरी सम्मिलित हों

एक पूर्ण बाहरी जुड़ाव हमें दोनों तालिकाओं से सभी रिकॉर्ड देगा, चाहे उनके पास दूसरी तालिका में मैच हो या नहीं, दोनों तरफ NULLs के साथ जहां कोई मैच नहीं है। परिणाम इस तरह दिखेगा:

1    Tim   1    Tim
2    Marta NULL NULL
NULL NULL  3    Katarina

हालाँकि, पाब्लो सांता क्रूज़ ने बताया, MySQL इस का समर्थन नहीं करता है। हम इस तरह से एक बाएं हाथ और एक सही शामिल होने का एक संघ कर इसका अनुकरण कर सकते हैं:

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

आप इस UNIONअर्थ के बारे में सोच सकते हैं कि "इन दोनों प्रश्नों को चलाएं, फिर परिणामों को एक दूसरे के ऊपर रखें"; कुछ पंक्तियाँ पहली क्वेरी से और कुछ दूसरी से आएंगी।

यह ध्यान दिया जाना चाहिए कि UNIONMySQL एक सटीक डुप्लिकेट को समाप्त कर देगा: टिम यहां दोनों प्रश्नों में दिखाई देगा, लेकिन UNIONएकमात्र परिणाम उसे एक बार सूचीबद्ध करता है। मेरे डेटाबेस गुरु सहयोगी को लगता है कि इस व्यवहार पर भरोसा नहीं किया जाना चाहिए। तो इसके बारे में अधिक स्पष्ट होने के लिए, हम WHEREदूसरी क्वेरी में एक खंड जोड़ सकते हैं :

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`
WHERE `t1`.`id` IS NULL;

दूसरी ओर, यदि आप किसी कारण से डुप्लिकेट देखना चाहते हैं , तो आप उपयोग कर सकते हैं UNION ALL


12
यह उत्तर एक वर्ष से अधिक पुराना है, लेकिन यह पता चला है कि श्री एटवुड ने 2007 में अपने ब्लॉग पर एक और बेहतर उत्तर दिया था: कोडिंगहोरर
नाथन लॉन्ग

4
MySQL के लिए आप वास्तव में UNION ALL के बजाय UNION के उपयोग से बचना चाहते हैं यदि कोई ओवरलैप नहीं है (ऊपर पावले की टिप्पणी देखें)। यदि आप अपने उत्तर में उस प्रभाव के लिए कुछ और जानकारी जोड़ सकते हैं, तो मुझे लगता है कि यह इस प्रश्न के लिए पसंदीदा उत्तर होगा क्योंकि यह अधिक गहन है।
Garen

2
"डेटाबेस गुरु सहयोगी" से सिफारिश सही है। संबंधपरक मॉडल (टेड कॉड और क्रिस डेट द्वारा किए गए सभी सैद्धांतिक काम) के संदर्भ में, अंतिम रूप की एक क्वेरी पूर्ण पूर्ण जॉइस का अनुकरण करती है, क्योंकि यह दो अलग-अलग सेटों को जोड़ती है, दूसरी क्वेरी "डुप्लिकेट" का परिचय नहीं देती है ( पंक्तियाँ पहले से ही पहले प्रश्न द्वारा लौटाई जाती हैं) जो कि a द्वारा निर्मित नहीं होंगी FULL OUTER JOIN। इस तरह के प्रश्नों को करने में गलत नहीं है, और उन डुप्लिकेट को हटाने के लिए UNION का उपयोग करना है। लेकिन वास्तव में एक को दोहराने के लिए FULL OUTER JOIN, हमें विरोधी में शामिल होने के लिए प्रश्नों में से एक की आवश्यकता है।
स्पेन्सर 7593

1
@IstiaqueAhmed: लक्ष्य एक पूर्ण OOO JOIN ऑपरेशन का अनुकरण करना है। हमें दूसरी क्वेरी में उस स्थिति की आवश्यकता है ताकि यह केवल उन पंक्तियों को लौटाए जिनके पास एक मैच नहीं है (एक एंटी-जॉइन पैटर्न।)। उस स्थिति के बिना, क्वेरी एक बाहरी जुड़ाव है ... यह पंक्तियों को उस मैच के साथ-साथ बिना मैच के भी लौटाता है। और जो पंक्तियाँ मेल खाती हैं वे पहले से ही पहले क्वेरी द्वारा वापस आ गईं थीं । यदि दूसरी क्वेरी उन्हीं पंक्तियों (फिर से) को वापस लाती है, तो हमने पंक्तियों की नकल की है और हमारा परिणाम एक पूर्ण ईमेल जॉइन के बराबर नहीं होगा ।
spencer7593

1
@IstiaqueAhmed: यह सच है कि एक UNIONऑपरेशन उन डुप्लिकेट को हटा देगा; लेकिन यह सभी डुप्लिकेट पंक्तियों को भी हटाता है, जिसमें डुप्लिकेट पंक्तियाँ भी शामिल हैं जो एक पूर्ण OOO JOIN द्वारा लौटा दी जाएंगी। अनुकरण करने के लिए a FULL JOIN b, सही पैटर्न है (a LEFT JOIN b) UNION ALL (b ANTI JOIN a)
spencer7593

35

unionक्वेरी का उपयोग करने से डुप्लिकेट हटा दिए जाएंगे, और यह उस व्यवहार से अलग है full outer joinजो कभी भी कोई डुप्लिकेट नहीं निकालता है:

[Table: t1]                            [Table: t2]
value                                  value
-------                                -------
1                                      1
2                                      2
4                                      2
4                                      5

यह अपेक्षित परिणाम है full outer join:

value | value
------+-------
1     | 1
2     | 2
2     | 2
Null  | 5
4     | Null
4     | Null

यह प्रयोग करने का परिणाम है leftऔर इसके right Joinसाथ union:

value | value
------+-------
Null  | 5 
1     | 1
2     | 2
4     | Null

[SQL Fiddle]

मेरा सुझाव दिया प्रश्न है:

select 
    t1.value, t2.value
from t1 
left outer join t2  
  on t1.value = t2.value
union all      -- Using `union all` instead of `union`
select 
    t1.value, t2.value
from t2 
left outer join t1 
  on t1.value = t2.value
where 
    t1.value IS NULL 

उपरोक्त क्वेरी का परिणाम अपेक्षित परिणाम के समान है:

value | value
------+-------
1     | 1
2     | 2
2     | 2
4     | NULL
4     | NULL
NULL  | 5

[SQL Fiddle]


@ शैव चेम्बर्स : [टिप्पणियों से, बहुत धन्यवाद के साथ!]
नोट: यह दक्षता के लिए और समान परिणाम उत्पन्न करने के लिए, दोनों का सबसे अच्छा समाधान हो सकता है FULL OUTER JOINयह ब्लॉग पोस्ट इसे अच्छी तरह से समझाता है - विधि 2 से उद्धृत करने के लिए: "यह डुप्लिकेट पंक्तियों को सही ढंग से संभालता है और इसमें कुछ भी शामिल नहीं होना चाहिए। यह UNION ALLसादे के बजाय उपयोग करने के लिए आवश्यक है UNION, जो उन डुप्लिकेट को समाप्त करना होगा जिन्हें मैं रखना चाहता हूं।" बड़े परिणाम सेट पर काफी अधिक कुशल हो सकता है, क्योंकि डुप्लिकेट को सॉर्ट करने और निकालने की कोई आवश्यकता नहीं है। ”


मैंने full outer joinविज़ुअलाइज़ेशन और गणित से आने वाले एक और समाधान को जोड़ने का फैसला किया , यह बेहतर नहीं है कि ऊपर लेकिन अधिक पठनीय:

पूर्ण बाहरी जुड़ने का अर्थ है (t1 ∪ t2): सभी में t1या t2
(t1 ∪ t2) = (t1 ∩ t2) + t1_only + t2_onlyसभी: दोनों में t1और इसके t2अलावा सभी में t1नहीं हैं t2और इसके अलावा सभी में t2नहीं हैं t1:

-- (t1 ∩ t2): all in both t1 and t2
select t1.value, t2.value
from t1 join t2 on t1.value = t2.value    
union all  -- And plus 
-- all in t1 that not exists in t2
select t1.value, null
from t1
where not exists( select 1 from t2 where t2.value = t1.value)    
union all  -- and plus
-- all in t2 that not exists in t1
select null, t2.value
from t2
where not exists( select 1 from t1 where t2.value = t1.value)

[SQL Fiddle]


हम एक ही कार्य को बार-बार कर रहे हैं, यदि t1 और t2 के लिए उप क्वेरी है तो mysql को एक ही कार्य को अधिक बार करना होगा, है ना? क्या हम इस स्थिति में उपनाम का उपयोग करके इसे हटा सकते हैं
कबीर हुसैन

मैं आपको कुछ अस्थायी तालिकाओं का उपयोग करने का सुझाव देता हूं;)।
shA.t

5
यह विधि दक्षता के लिए और दोनों के लिए एक ही परिणाम उत्पन्न करने के लिए सबसे अच्छा समाधान है FULL OUTER JOINयह ब्लॉग पोस्ट इसे अच्छी तरह से समझाता है - विधि 2 से उद्धृत करने के लिए: "यह डुप्लिकेट पंक्तियों को सही ढंग से संभालता है और इसमें कुछ भी शामिल नहीं है। इसे सादे यूनिअन के बजाय UNION ALL का उपयोग करना आवश्यक है, जो मैं डुप्लिकेट को समाप्त करना चाहता हूं। बड़े परिणाम सेट पर यह काफी अधिक कुशल हो सकता है, क्योंकि डुप्लिकेट को छाँटने और निकालने की कोई आवश्यकता नहीं है। "
स्टीव चैम्बर्स

2
@SteveChambers बहुत देर हो चुकी है, लेकिन आपकी टिप्पणी के लिए धन्यवाद। मैंने आपकी टिप्पणी को फिर से हाइलाइट किए गए उत्तर के लिए जोड़ा, यदि आप सहमत नहीं हैं तो कृपया इसे वापस रोल करें;)।
शौ।

कोई समस्या नहीं @ shA.t - IMO के पास वास्तव में अधिक upvotes और / या स्वीकृत उत्तर होना चाहिए।
स्टीव चैम्बर्स 15

6

MySql में FULL-OUTER-JOIN सिंटैक्स नहीं है। आपको LEFT JOIN और RIGHT JOIN दोनों को निम्नानुसार अनुकरण करना होगा-

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id  
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

लेकिन MySql में राइट जॉइन सिंटैक्स भी नहीं है। MySql के बाहरी जुड़ाव सरलीकरण के अनुसार , दाईं ओर जुड़ने को क्वेरी में t1 और t2 को स्विच FROMऔर ONक्लॉज में बदलकर समतुल्य बाएं जोड़ में बदल दिया जाता है । इस प्रकार, MySql क्वेरी ऑप्टिमाइज़र मूल क्वेरी का निम्न में अनुवाद करता है -

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id  
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id

अब, जैसा कि है, वैसे मूल प्रश्न लिखने में कोई बुराई नहीं है, लेकिन यह कहें कि यदि आपके पास WHERE क्लॉज की तरह विधेय है, जो कि पहले से शामिल होने वाले या AND और विधेय पर आधारित है ON, जो कि एक पूर्व -ज्वाइन समर्पित है, तो आप शैतान पर एक नज़र डालना चाहते हैं; जो विवरण में है।

MySql क्वेरी ऑप्टिमाइज़र नियमित रूप से विधेय की जाँच करता है यदि वे शून्य-अस्वीकृत हैंअशक्त-निरूपित परिभाषा और उदाहरण अब, यदि आपने राइट जॉइन कर लिया है, लेकिन t1 से कॉलम पर पहले से ही भविष्यवाणी कर दी है, तो आपको अशक्त परिदृश्य में चलने का खतरा हो सकता है।

उदाहरण के लिए, निम्नलिखित क्वेरी -

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'

क्वेरी ऑप्टिमाइज़र द्वारा निम्नलिखित का अनुवाद किया जाता है-

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
WHERE t1.col1 = 'someValue'

इसलिए तालिकाओं का क्रम बदल गया है, लेकिन विधेय अभी भी t1 पर लागू होता है, लेकिन t1 अब 'ON' क्लॉज में है। यदि t1.col1 को NOT NULL स्तंभ के रूप में परिभाषित किया जाता है, तो यह क्वेरी शून्य-अस्वीकृत हो जाएगी ।

कोई भी बाहरी-जुड़ाव (बाएं, दाएं, पूर्ण) जो नल-अस्वीकृत है, MySql द्वारा इनर-जॉइन में परिवर्तित हो जाता है।

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


4

SQLite में आपको यह करना चाहिए:

SELECT * 
FROM leftTable lt 
LEFT JOIN rightTable rt ON lt.id = rt.lrid 
UNION
SELECT lt.*, rl.*  -- To match column set
FROM rightTable rt 
LEFT JOIN  leftTable lt ON lt.id = rt.lrid

क्या हम इसका उपयोग कर सकते हैं? जैसे: सेलेक्ट * FECT लेफ्टटेबल लेफ्टिनेंट लेफ्टिनेंट जॉइन राइट राइटटेबल पर lt.id = rt.lrid यूनिअन सिलेक्ट लेफ्टिनेंट। *, आरएल। ;
कबीर हुसैन

हाँ, लेकिन SQLite राइट
जॉइन का

4

उपरोक्त उत्तरों में से कोई भी वास्तव में सही नहीं है, क्योंकि वे दोहरावित मूल्यों के होने पर शब्दार्थ का पालन नहीं करते हैं।

एक क्वेरी के लिए जैसे (इस डुप्लिकेट से ):

SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.Name = t2.Name;

सही समतुल्य है:

SELECT t1.*, t2.*
FROM (SELECT name FROM t1 UNION  -- This is intentionally UNION to remove duplicates
      SELECT name FROM t2
     ) n LEFT JOIN
     t1
     ON t1.name = n.name LEFT JOIN
     t2
     ON t2.name = n.name;

यदि आपको इसके लिए NULLमूल्यों के साथ काम करने की आवश्यकता है (जो आवश्यक भी हो सकता है), तो इसके बजाय NULL-safe तुलना ऑपरेटर का उपयोग करें ।<=>=


3
यह अक्सर एक अच्छा समाधान होता है, लेकिन FULL OUTER JOINजब भी nameकॉलम शून्य होता है , तो यह अलग परिणाम दे सकता है। union allविरोधी में शामिल होने के पैटर्न के साथ क्वेरी बाहरी सही ढंग से व्यवहार में शामिल होने के पुन: पेश करना चाहिए, लेकिन जो समाधान अधिक उपयुक्त संदर्भ पर और बाधाओं कि टेबल पर सक्रिय हैं पर निर्भर करता है।
फेथिला

@ फेथीला । । यह एक अच्छी बात है। मैंने उत्तर समायोजित कर दिया।
गॉर्डन लिनोफ

1
ठीक है, लेकिन अशक्त-सुरक्षित तुलना ऑपरेटर सफल हो जाएगा, जो पूर्ण बाहरी जुड़ने के व्यवहार से अलग है, यदि आपके पास t1 और t2 दोनों में अशक्त नाम हैं
fthiella

@ फेथीला । । मुझे ऐसा करने के सबसे अच्छे तरीके के बारे में सोचना होगा। लेकिन स्वीकृत उत्तर कितना गलत है, यह देखते हुए, लगभग कुछ भी सही उत्तर के करीब है। (यह उत्तर गलत है यदि दोनों ओर कई कुंजियाँ हैं।)
गॉर्डन लिनोफ़

1
हां स्वीकृत उत्तर गलत है, एक सामान्य समाधान के रूप में, मुझे लगता है कि यह उपयोग करने के लिए सही है union all, लेकिन यह उत्तर पहले या दूसरे प्रश्न में एक एंटी-जॉइन पैटर्न को याद करता है जो मौजूदा डुप्लिकेट को बनाए रखेगा लेकिन नए को जोड़ने से रोकता है। संदर्भ के आधार पर अन्य समाधान (जैसे यह) अधिक उपयुक्त हो सकते हैं।
फेथिला

3

अधिक स्पष्टता के लिए संशोधित shA.t की क्वेरी:

-- t1 left join t2
SELECT t1.value, t2.value
FROM t1 LEFT JOIN t2 ON t1.value = t2.value   

    UNION ALL -- include duplicates

-- t1 right exclude join t2 (records found only in t2)
SELECT t1.value, t2.value
FROM t1 RIGHT JOIN t2 ON t1.value = t2.value
WHERE t2.value IS NULL 

3

आप निम्न कार्य कर सकते हैं:

(SELECT 
    *
FROM
    table1 t1
        LEFT JOIN
    table2 t2 ON t1.id = t2.id
WHERE
    t2.id IS NULL)
UNION ALL
 (SELECT 
    *
FROM
    table1 t1
        RIGHT JOIN
    table2 t2 ON t1.id = t2.id
WHERE
    t1.id IS NULL);

1

क्रॉस ज्वाइन सॉल्यूशन के बारे में आप क्या कहेंगे ?

SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2 
ON 1=1;

2
नहीं, यह एक क्रॉस जॉइन है। यह t1 में हर पंक्ति को t2 में हर पंक्ति से मिलाएगा, select (select count(*) from t1) * (select count(*) from t2))परिणाम सेट में पंक्तियों के साथ सभी संभावित संयोजनों के सेट को पैदावार देता है ।
मार्क एल।

इस कोड को इस सवाल का जवाब कर सकते हैं, के बारे में अतिरिक्त संदर्भ प्रदान करने के लिए कैसे और क्यों यह हल करती है समस्या जवाब की दीर्घकालिक मूल्य में सुधार होगा।
अलेक्जेंडर

कौन सा जोड़ मददगार हो सकता है? शायद उदाहरण के लिए?
सुपर मारियो


0

यह संभव भी है, लेकिन आपको समान फ़ील्ड नामों का चयन करना होगा।

SELECT t1.name, t2.name FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT t1.name, t2.name FROM t2
LEFT JOIN t1 ON t1.id = t2.id

यह केवल बाईं ओर से परिणाम दोहरा रहा है।
मैथ्यू पढ़ें

-1

मैं प्रतिक्रिया को ठीक करता हूं, और कार्यों में सभी पंक्तियां शामिल हैं (पावेल लेकिक की प्रतिक्रिया के आधार पर)

    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    WHERE b.`key` is null
    )
    UNION ALL
    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    where  a.`key` = b.`key`
    )
    UNION ALL
    (
    SELECT b.* FROM tablea a
    right JOIN tableb b ON b.`key` = a.key
    WHERE a.`key` is null
    );

नहीं, यह एक प्रकार का "आउटर-ओनली" जॉइन है, जो केवल उन पंक्तियों को लौटाएगा जिनमें से tableaमैच नहीं है tablebऔर इसके विपरीत। आप कोशिश करते हैं UNION ALL, जो केवल तभी काम करेगा जब इन दो तालिकाओं में समान रूप से आदेशित कॉलम हों, जिनकी गारंटी नहीं है।
मार्क एल।

यह काम करता है, मैं अस्थायी डेटाबेस (1,2,3,4,5,6) और टेबलब (4,5,6,7,8,9) बनाता हूं, इसकी पंक्तियों में 3 कॉल "आईडी", "नंबर" हैं। पाठ के रूप में "name_number", और परिणाम में केवल (1,2,3,7,8,9) काम करता है
Ruben Ruíz

1
वह बाहरी जुड़ाव नहीं है। एक बाहरी जुड़ाव में मिलान करने वाले सदस्य भी शामिल हैं।
मार्क एल।

उस नए वाक्य में सभी परिणाम 1,2, ..., 9
Rubén Ruíz

-2

उत्तर:

SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id;

निम्नानुसार फिर से बनाया जा सकता है:

 SELECT t1.*, t2.* 
 FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp
 LEFT JOIN t1 ON t1.id = tmp.id
 LEFT JOIN t2 ON t2.id = tmp.id;

UNION या UNION का उपयोग करना सभी उत्तर किनारे के मामले को कवर नहीं करता है, जहां बेस टेबल में डुप्लिकेट प्रविष्टियां होती हैं।

स्पष्टीकरण:

वहाँ एक किनारे मामला है कि एक संघ या यूनिअन सभी को कवर नहीं किया जा सकता है। हम mysql पर इसका परीक्षण नहीं कर सकते क्योंकि यह पूर्ण OUTER JOINs का समर्थन नहीं करता है, लेकिन हम इसका समर्थन करने वाले डेटाबेस पर चित्रण कर सकते हैं:

 WITH cte_t1 AS
 (
       SELECT 1 AS id1
       UNION ALL SELECT 2
       UNION ALL SELECT 5
       UNION ALL SELECT 6
       UNION ALL SELECT 6
 ),
cte_t2 AS
(
      SELECT 3 AS id2
      UNION ALL SELECT 4
      UNION ALL SELECT 5
      UNION ALL SELECT 6
      UNION ALL SELECT 6
)
SELECT  *  FROM  cte_t1 t1 FULL OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2;

This gives us this answer:

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

यूनिअन समाधान:

SELECT  * FROM  cte_t1 t1 LEFT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2
UNION    
SELECT  * FROM cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

गलत उत्तर देता है:

 id1  id2
NULL  3
NULL  4
1  NULL
2  NULL
5  5
6  6

यूनिअन ऑल सॉल्यूशन:

SELECT  * FROM cte_t1 t1 LEFT OUTER join cte_t2 t2 ON t1.id1 = t2.id2
UNION ALL
SELECT  * FROM  cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

भी गलत है।

id1  id2
1  NULL
2  NULL
5  5
6  6
6  6
6  6
6  6
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

जबकि यह प्रश्न:

SELECT t1.*, t2.*
FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp 
LEFT JOIN t1 ON t1.id = tmp.id 
LEFT JOIN t2 ON t2.id = tmp.id;

निम्नलिखित देता है:

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

आदेश अलग है, लेकिन अन्यथा सही उत्तर से मेल खाता है।


यह प्यारा है, लेकिन UNION ALLसमाधान को गलत तरीके से प्रस्तुत करता है। इसके अलावा, यह एक समाधान प्रस्तुत करता है UNIONजिसके उपयोग से आवश्यक डी-डुप्लीकेशन के कारण बड़े स्रोत तालिकाओं पर धीमी हो जाएगी। अंत में, यह संकलित नहीं करेगा, क्योंकि क्षेत्र idउपकुंजी में मौजूद नहीं है tmp
मार्क एल।

मैंने कभी भी गति के बारे में दावा नहीं किया, और न ही ओपी ने गति के बारे में कुछ भी उल्लेख किया। यूनिअन ऑल्ट को मान लें (आप निर्दिष्ट नहीं करते कि कौन सा है) और यह दोनों सही उत्तर देते हैं, अगर हम यह दावा करना चाहते हैं कि एक तेज है, तो हमें बेंचमार्क प्रदान करना होगा, और यह ओपी से पचा होगा। सवाल।
एंजेलोस

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

3
गलतियाँ: " UNION ALLसमाधान: ... यह भी गलत है।" आपके द्वारा प्रस्तुत कोड दाएं-जुड़ने ( where t1.id1 is null) से प्रदान किए जाने वाले चौराहे-बहिष्करण को छोड़ देता है UNION ALL। जो कहना है, आपका समाधान अन्य सभी को रौंदता है, केवल जब उन अन्य समाधानों में से एक को गलत तरीके से लागू किया जाता है। "क्यूटनेस" पर, बिंदु को लिया गया। वह कृतज्ञ था, मेरी क्षमायाचना।
मार्क एल।

-3

SQL मानक कहता full join onहै कि inner join onपंक्तियाँ union allnulls द्वारा फैली हुई बेजोड़ तालिकाएँ हैं, nulls द्वारा union allदाएँ तालिका पंक्तियों को बढ़ाया गया है। यानी inner join onपंक्तियाँ union allपंक्तियों में हैं, left join onलेकिन inner join on union allपंक्तियों में right join onनहीं inner join on

यानी left join onपंक्तियाँ अंदर union all right join onनहीं inner join on। या यदि आप जानते हैं कि आपका inner join onपरिणाम किसी विशेष राइट टेबल कॉलम में शून्य नहीं हो सकता है, तो " right join onपंक्तियों में inner join on" उस कॉलम द्वारा विस्तारित स्थिति के right join onसाथ पंक्तियाँ नहीं हैं ।onandis null

यानी इसी तरह right join on union allउपयुक्त left join onपंक्तियाँ।

से के बीच "आंतरिक शामिल हों" और "बाहरी शामिल हों" क्या अंतर है? :

(एसक्यूएल स्टैंडर्ड 2006 एसक्यूएल / फाउंडेशन 7.7 सिंटेक्स नियम 1, सामान्य नियम 1 बी, 3 सी एंड डी, 5 बी।)

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