बाहरी जुड़ाव आज केंद्र स्तर पर है। और यह SQL जॉइन करने के लिए आपके अंतिम गाइड का भाग 2 है। यदि आप भाग 1 से चूक गए हैं, तो यह लिंक है।
इसे देखने से बाहरी आंतरिक के विपरीत है। हालाँकि, यदि आप इस तरह से बाहरी जुड़ाव पर विचार करते हैं, तो आप भ्रमित होंगे। इसके शीर्ष पर, आपको बाहरी . शब्द शामिल करने की आवश्यकता नहीं है आपके वाक्यविन्यास में स्पष्ट रूप से। यह वैकल्पिक है!
लेकिन इससे पहले कि हम गोता लगाएँ, आइए बाहरी जुड़ावों से संबंधित नल पर चर्चा करें।
अशक्त और बाहरी जॉइन
जब आप 2 तालिकाओं में शामिल होते हैं, तो किसी भी तालिका में से कोई एक मान शून्य हो सकता है। इनर जॉइन के लिए, नल वाले रिकॉर्ड मेल नहीं खाएंगे, और उन्हें छोड़ दिया जाएगा और परिणाम सेट में दिखाई नहीं देंगे। यदि आप ऐसे रिकॉर्ड प्राप्त करना चाहते हैं जो मेल नहीं खाते हैं, तो आपका एकमात्र विकल्प OUTER JOIN है।
विलोम पर वापस जा रहे हैं, क्या यह INNER JOINs के विपरीत नहीं है? पूरी तरह से नहीं, जैसा कि आप अगले भाग में देखेंगे।
SQL सर्वर OUTER JOIN के बारे में सब कुछ
बाहरी जुड़ाव को समझना आउटपुट से शुरू होता है। आप जो उम्मीद कर सकते हैं उसकी पूरी सूची यहां दी गई है:
- सभी रिकॉर्ड जो शामिल होने की स्थिति या विधेय से मेल खाते हैं। यह ON कीवर्ड के ठीक बाद की अभिव्यक्ति है, बहुत कुछ INNER JOIN आउटपुट की तरह। हम इस मुद्दे को आंतरिक पंक्ति . के रूप में संदर्भित करते हैं ।
- गैर-शून्य मान बाएं . से दाएं . से शून्य समकक्षों वाली तालिका टेबल। हम इस मुद्दे को बाहरी पंक्तियों . के रूप में संदर्भित करते हैं ।
- गैर-शून्य मान दाएं . से बाएं . से शून्य समकक्षों वाली तालिका टेबल। यह बाहरी पंक्तियों का दूसरा रूप है।
- आखिरकार, यह ऊपर वर्णित सभी चीजों का संयोजन हो सकता है।
उस सूची के साथ, हम कह सकते हैं कि OUTER JOIN आंतरिक और बाहरी पंक्तियों को लौटाता है ।
- आंतरिक - क्योंकि इनर जॉइन के सटीक परिणाम हो सकते हैं लौटा।
- बाहरी - क्योंकि बाहरी पंक्तियाँ भी हो सकती हैं लौटा।
यह INNER JOIN से अंतर है।
इनर केवल रिटर्न इनर पंक्तियों में शामिल होता है। बाहरी जोड़ आंतरिक और बाहरी दोनों पंक्तियों को वापस कर सकते हैं
ध्यान दें कि मैंने "हो सकता है" और "भी हो सकता है" का इस्तेमाल किया। यह आपके WHERE क्लॉज पर निर्भर करता है (या यदि आपने कभी WHERE क्लॉज शामिल किया है) यदि यह आंतरिक और/या बाहरी दोनों पंक्तियों को लौटाता है।
लेकिन एक सेलेक्ट स्टेटमेंट से, आप यह कैसे निर्धारित कर सकते हैं कि बाईं या दायीं टेबल कौन सी है ? अच्छा सवाल!
कैसे पता करें कि जॉइन में कौन सी लेफ्ट या राइट टेबल है?
हम इस प्रश्न का उत्तर उदाहरणों के साथ दे सकते हैं:
SELECT *
FROM Table1 a
LEFT OUTER JOIN Table2 b on a.column1 = b.column1
ऊपर के उदाहरण से, तालिका1 बाईं तालिका है, और तालिका2 सही तालिका है। अब एक और उदाहरण लेते हैं। इस बार, यह एक साधारण मल्टी-जॉइन है।
SELECT *
FROM Table1 a
LEFT OUTER JOIN Table2 b on a.column1 = b.column1
LEFT OUTER JOIN Table3 c on b.column2 = c.column1
इस मामले में, यह जानने के लिए कि बाएँ या दाएँ क्या है, याद रखें कि जॉइन 2 टेबल पर काम करता है।
तालिका1 अभी भी बाईं तालिका है, और तालिका2 सही तालिका है। यह 2 तालिकाओं में शामिल होने को संदर्भित करता है:तालिका1 और तालिका2 . तालिका2 . में शामिल होने के बारे में क्या और तालिका3 ? तालिका2 बाईं तालिका बन जाती है, और तालिका3 सही तालिका है।
अगर हम चौथी तालिका जोड़ते हैं, तालिका3 बाईं तालिका बन जाती है, और तालिका4 सही तालिका है। लेकिन यह वहां खत्म नहीं होता है। हम तालिका1 . में दूसरी तालिका में शामिल हो सकते हैं . यहां एक उदाहरण दिया गया है:
SELECT *
FROM Table1 a
LEFT OUTER JOIN Table2 b on a.column1 = b.column1
LEFT OUTER JOIN Table3 c on b.column2 = c.column1
LEFT OUTER JOIN Table4 d on c.column1 = d.column2
LEFT OUTER JOIN Table5 e on a.column2 = e.column1
तालिका1 बाईं तालिका है, और तालिका5 सही तालिका है। आप अन्य तालिकाओं के साथ भी ऐसा ही कर सकते हैं।
ठीक है, आइए उपरोक्त अपेक्षित आउटपुट की सूची पर वापस जाएं। हम इनसे बाहरी जुड़ाव प्रकार भी प्राप्त कर सकते हैं।
बाहरी जुड़ाव के प्रकार
OUTER JOIN आउटपुट के आधार पर 3 प्रकार होते हैं।
बाएं बाहरी शामिल हों (बाएं शामिल हों)
LEFT JOIN बाएं से आंतरिक पंक्तियों + गैर-शून्य मान लौटाता है सही तालिका के अशक्त समकक्षों के साथ तालिका। इसलिए, यह लेफ्ट जॉइन है क्योंकि लेफ्ट टेबल गैर-नल वैल्यू वाले जॉइन के भीतर दो टेबलों में प्रमुख है।
बाएं बाहरी उदाहरण 1 में शामिल हों
-- Return all customerIDs with orders and no orders
USE AdventureWorks
GO
SELECT
c.CustomerID
,soh.OrderDate
FROM Sales.Customer c
LEFT OUTER JOIN Sales.SalesOrderHeader soh ON c.CustomerID = soh.CustomerID
ऊपर के उदाहरण में, ग्राहक बाईं तालिका है, और SalesOrderHeader सही तालिका है। क्वेरी का परिणाम है 32,166 रिकॉर्ड - इसमें आंतरिक और बाहरी दोनों पंक्तियाँ शामिल हैं। आप इसका एक भाग चित्र 1 में देख सकते हैं:
मान लीजिए कि हम केवल बाहरी पंक्तियों को या बिना ऑर्डर वाले ग्राहकों को वापस करना चाहते हैं। ऐसा करने के लिए, SalesOrderHeader से केवल नल वाली पंक्तियों को शामिल करने के लिए WHERE क्लॉज जोड़ें ।
SELECT
c.CustomerID
,soh.OrderDate
FROM Sales.Customer c
LEFT OUTER JOIN Sales.SalesOrderHeader soh ON c.CustomerID = soh.CustomerID
WHERE soh.SalesOrderID IS NULL
मुझे जो परिणाम सेट मिला है वह है 701 रिकॉर्ड . उन सभी को शून्य पसंद है आदेश दिनांक चित्र 1 से।
अगर मुझे केवल आंतरिक पंक्तियाँ मिलती हैं, तो परिणाम 31,465 रिकॉर्ड . होगा . मैं उन SalesOrderIDs . को शामिल करने के लिए WHERE क्लॉज को बदलकर ऐसा कर सकता हूं जो शून्य नहीं हैं। या मैं जॉइन को इनर जॉइन में बदल सकता हूं और WHERE क्लॉज को हटा सकता हूं।
यह देखने के लिए कि क्या यह WHERE क्लॉज के बिना पहले उदाहरण के आउटपुट से चेक आउट करता है, आइए रिकॉर्ड्स का योग करें।
आंतरिक पंक्तियां | बाहरी पंक्तियाँ | कुल पंक्तियाँ |
31,465 रिकॉर्ड | 701 रिकॉर्ड | 32,166 रिकॉर्ड |
32,166 रिकॉर्ड के साथ ऊपर की कुल पंक्तियों से, आप देख सकते हैं कि यह पहले उदाहरण के परिणामों के साथ जाँच करता है। इससे यह भी पता चलता है कि LEFT OUTER JOIN कैसे काम करता है।
बाएं बाहरी उदाहरण 2 में शामिल हों
इस बार, उदाहरण एक बहु-जुड़ना है। यह भी ध्यान दें कि हम OUTER कीवर्ड को हटा देते हैं।
-- show the people with and without addresses from AdventureWorks
USE AdventureWorks
GO
SELECT
P.FirstName
,P.MiddleName
,P.LastName
,a.AddressLine1
,a.AddressLine2
,a.City
,adt.Name AS AddressType
FROM Person.Person p
LEFT JOIN Person.BusinessEntityAddress bea ON P.BusinessEntityID = bea.BusinessEntityID
LEFT JOIN Person.Address a ON bea.AddressID = a.AddressID
LEFT JOIN person.AddressType adt ON bea.AddressTypeID = adt.AddressTypeID
इसने 19,996 रिकॉर्ड बनाए। आप नीचे चित्र 2 में आउटपुट के भाग को देख सकते हैं। शून्य के साथ रिकॉर्ड AddressLine1 बाहरी पंक्तियाँ हैं। इसके ऊपर भीतरी पंक्तियाँ हैं।
राइट आउटर जॉइन (राइट जॉइन)
राइट जॉइन दाएं . से आंतरिक पंक्तियों + गैर-शून्य मान लौटाता है बाईं तालिका के शून्य समकक्षों के साथ तालिका।
दायां बाहरी जॉइन उदाहरण 1
-- From the product reviews, return the products without product reviews
USE AdventureWorks
GO
SELECT
P.Name
FROM Production.ProductReview pr
RIGHT OUTER JOIN Production.Product p ON pr.ProductID = p.ProductID
WHERE pr.ProductReviewID IS NULL
चित्र 3 परिणाम सेट में 501 में से 10 रिकॉर्ड दिखाता है।
उपरोक्त उदाहरण में, ProductReview बाईं तालिका है, और उत्पाद सही तालिका है। चूंकि यह एक राइट आउटर जॉइन है, इसलिए हम सही टेबल से नॉन-न्यूल वैल्यू को शामिल करना चाहते हैं।
हालाँकि, लेफ्ट जॉइन या राइट जॉइन के बीच चयन आप पर निर्भर करता है। क्यों? क्योंकि आप क्वेरी व्यक्त कर सकते हैं, चाहे बाएं या दाएं शामिल हों, और वही परिणाम प्राप्त करें। आइए इसे लेफ्ट जॉइन के साथ आज़माएं।
-- return the products without product reviews using LEFT OUTER JOIN
USE AdventureWorks
GO
SELECT
P.Name
FROM Production.Product p
LEFT OUTER JOIN Production.ProductReview pr ON pr.ProductID = p.ProductID
WHERE pr.ProductReviewID IS NULL
उपरोक्त को निष्पादित करने का प्रयास करें, और आपके पास चित्र 3 जैसा ही परिणाम होगा। लेकिन क्या आपको लगता है कि क्वेरी ऑप्टिमाइज़र उनके साथ अलग व्यवहार करेगा? आइए चित्र 4 में दोनों की निष्पादन योजना में पता करें।
यदि आप इसके लिए नए हैं, तो निष्पादन योजना में कुछ आश्चर्य हैं।
- आरेख एक जैसे दिखते हैं, और वे हैं:शोप्लान की तुलना करें . आज़माएं , और आपको वही QueryPlanHash . दिखाई देगा ।
- मर्ज जॉइन के साथ शीर्ष आरेख पर ध्यान दें। हमने राइट आउटर जॉइन का इस्तेमाल किया, लेकिन SQL सर्वर ने इसे लेफ्ट आउटर जॉइन में बदल दिया। इसने बाएँ और दाएँ तालिकाओं को भी स्विच किया। यह इसे LEFT JOIN के साथ दूसरी क्वेरी के बराबर बनाता है।
जैसा कि आप अभी देख रहे हैं, परिणाम वही हैं। इसलिए, चुनें कि कौन से OUTER JOINs अधिक सुविधाजनक होंगे।
SQL सर्वर ने राइट जॉइन को लेफ्ट जॉइन में क्यों बदला?
डेटाबेस इंजन को तार्किक जुड़ाव व्यक्त करने के तरीके का पालन करने की आवश्यकता नहीं है। जब तक यह संभव के रूप में सबसे तेज़ तरीके से सही परिणाम दे सकता है, तब तक यह परिवर्तन करेगा। यहां तक कि शॉर्टकट भी।
यह निष्कर्ष न निकालें कि RGHT जॉइन खराब है और लेफ्ट जॉइन अच्छा है।
दायां बाहरी जॉइन उदाहरण 2
नीचे दिए गए उदाहरण पर एक नज़र डालें:
-- Get the unassigned addresses and the address types with no addresses
SELECT
P.FirstName
,P.MiddleName
,P.LastName
,a.AddressLine1
,a.AddressLine2
,a.City
,adt.Name AS AddressType
FROM Person.Person p
RIGHT JOIN Person.BusinessEntityAddress bea ON P.BusinessEntityID = bea.BusinessEntityID
RIGHT JOIN Person.Address a ON bea.AddressID = a.AddressID
RIGHT JOIN person.AddressType adt ON bea.AddressTypeID = adt.AddressTypeID
WHERE P.BusinessEntityID IS NULL
आप इस प्रश्न से 2 चीजें प्राप्त कर सकते हैं, जैसा कि आप नीचे चित्र 5 में देख सकते हैं:
क्वेरी परिणाम निम्नलिखित दिखाते हैं:
- असाइन किए गए पते - ये रिकॉर्ड शून्य नामों वाले हैं।
- पते के प्रकार जिनमें कोई पता नहीं है। संग्रह, बिलिंग और प्राथमिक पता प्रकारों का कोई संगत पता नहीं है। वे रिकॉर्ड 817 से 819 तक हैं।
पूर्ण बाहरी जॉइन (पूर्ण जॉइन)
FULL JOIN बाएँ और दाएँ, भीतरी पंक्तियों और बाहरी पंक्तियों का संयोजन देता है।
-- Get people with and without addresses, unassigned addresses, and address types without addresses
SELECT
P.FirstName
,P.MiddleName
,P.LastName
,a.AddressLine1
,a.AddressLine2
,a.City
,adt.Name AS AddressType
FROM Person.Person p
FULL JOIN Person.BusinessEntityAddress bea ON P.BusinessEntityID = bea.BusinessEntityID
FULL JOIN Person.Address a ON bea.AddressID = a.AddressID
FULL JOIN person.AddressType adt ON bea.AddressTypeID = adt.AddressTypeID
परिणाम सेट में 20,815 रिकॉर्ड शामिल हैं। आपकी अपेक्षा के अनुरूप, यह इनर जॉइन, लेफ्ट जॉइन और राइट जॉइन के परिणाम सेट से रिकॉर्ड की कुल संख्या है।
बाएँ और दाएँ जॉइन में एक WHERE क्लॉज़ शामिल है जो केवल बाएँ या दाएँ तालिकाओं में नल के साथ परिणाम दिखाता है।
इनर जॉइन | बाएं शामिल हों (जहां a.AddressID खाली है) | राइट जॉइन (जहां P.BusinessEntityID IS NULL है) | कुल (पूर्ण जॉइन के समान) |
18,798 रिकॉर्ड | 1,198 रिकॉर्ड | 819 रिकॉर्ड | 20,815 रिकॉर्ड |
ध्यान दें कि FULL JOIN बड़ी तालिकाओं से एक बड़ा परिणाम सेट कर सकता है। इसलिए, इसका उपयोग तभी करें जब आपको इसकी आवश्यकता हो।
बाहरी जॉइन के व्यावहारिक उपयोग
यदि आप अभी भी संकोच करते हैं और जब आप OUTER JOIN का उपयोग कर सकते हैं और करना चाहिए, तो यहां कुछ उपाय दिए गए हैं।
बाहरी उस आउटपुट से जुड़ता है जो आंतरिक और बाहरी दोनों पंक्तियों को आउटपुट करता है
उदाहरण हो सकते हैं:
- भुगतान किए गए और भुगतान न किए गए ग्राहक आदेशों की वर्णानुक्रमिक सूची।
- मंदी या बिना मंदता वाले कर्मचारियों की वर्णानुक्रमिक सूची।
- उन पॉलिसीधारकों की सूची जिन्होंने अपनी नवीनतम बीमा पॉलिसियों का नवीनीकरण किया और नवीनीकरण नहीं किया।
आउटर जॉइन कि आउटपुट आउटर रो ओनली
उदाहरणों में शामिल हैं:
- शून्य-मंदता पुरस्कार के लिए कोई मंदता रिकॉर्ड वाले कर्मचारियों की वर्णानुक्रमिक सूची
- बिना ग्राहकों वाले क्षेत्रों की सूची
- किसी विशेष उत्पाद की बिक्री न करने वाले बिक्री एजेंटों की सूची
- अनुपलब्ध मानों से परिणाम प्राप्त करना, जैसे किसी निश्चित अवधि में बिक्री आदेश के बिना दिनांक (नीचे उदाहरण)
- नोड्स के माता-पिता-बच्चे के संबंध में कोई बच्चा नहीं है (नीचे उदाहरण)
अनुपलब्ध मानों से परिणाम प्राप्त करना
मान लीजिए आपको एक रिपोर्ट तैयार करने की आवश्यकता है। उस रिपोर्ट में किसी निश्चित अवधि में प्रत्येक माह के लिए दिनों की संख्या दर्शानी चाहिए, जहां कोई आदेश नहीं थे। SalesOrderHeader एडवेंचरवर्क्स . में आदेश दिनांक . शामिल है , लेकिन उनके पास बिना ऑर्डर वाली तारीखें नहीं हैं। आप क्या कर सकते हैं?
<एच5>1. किसी अवधि में सभी तिथियों की तालिका बनाएंनीचे दी गई एक नमूना स्क्रिप्ट पूरे 2014 के लिए तिथियों की एक तालिका तैयार करेगी:
DECLARE @StartDate date = '20140101', @EndDate date = '20141231';
CREATE TABLE dbo.Dates
(
d DATE NOT null PRIMARY KEY
)
WHILE @StartDate <= @EndDate
BEGIN
INSERT Dates([d]) SELECT @StartDate;
SET @StartDate = DATEADD(DAY, 1, @StartDate);
END
SELECT d FROM Dates ORDER BY [d];
2. बिना ऑर्डर वाले दिनों को आउटपुट करने के लिए लेफ्ट जॉइन का उपयोग करें
SELECT
MONTH(d.d) AS [month]
,YEAR(d.d) AS [year]
,COUNT(*) AS NoOrderDays
FROM Dates d
LEFT JOIN Sales.SalesOrderHeader soh ON d.d = soh.OrderDate
WHERE soh.OrderDate IS NULL
GROUP BY YEAR(d.d), MONTH(d.d)
ORDER BY [year], [month]
उपरोक्त कोड उन दिनों की संख्या को गिनता है जब कोई आदेश नहीं दिया गया हो। SalesOrderHeader आदेश के साथ तिथियां शामिल हैं। इसलिए, शामिल होने में लौटाए गए नल बिना आदेश के दिनों के रूप में गिने जाएंगे।
इस बीच, यदि आप सटीक तिथियां जानना चाहते हैं, तो आप गिनती और समूहीकरण को हटा सकते हैं।
SELECT
d.d
,soh.OrderDate
FROM Dates d
LEFT JOIN Sales.SalesOrderHeader soh ON d.d = soh.OrderDate
WHERE soh.OrderDate IS NULL
या, यदि आप किसी निश्चित अवधि में ऑर्डर गिनना चाहते हैं और देखना चाहते हैं कि किस तारीख में शून्य ऑर्डर हैं, तो यहां बताया गया है:
SELECT DISTINCT
D.d AS SalesDate
,COUNT(soh.OrderDate) AS NoOfOrders
FROM Dates d
LEFT JOIN Sales.SalesOrderHeader soh ON d.d = soh.OrderDate
WHERE d.d BETWEEN '02/01/2014' AND '02/28/2014'
GROUP BY d.d
ORDER BY d.d
उपरोक्त कोड फरवरी 2014 के आदेशों की गणना करता है। परिणाम देखें:
यह 3 फरवरी 2014 को क्यों उजागर करता है? एडवेंचरवर्क्स की मेरी कॉपी में, उस तारीख के लिए कोई बिक्री आदेश नहीं है।
अब, नोटिस COUNT(soh.OrderDate) कोड में। बाद में, हम स्पष्ट करेंगे कि यह इतना महत्वपूर्ण क्यों है।
माता-पिता-बच्चे के संबंधों में संतानहीन नोड्स प्राप्त करना
कभी-कभी हमें माता-पिता-बच्चे के रिश्ते में बिना बच्चे वाले नोड्स को जानने की जरूरत होती है।
आइए उस डेटाबेस का उपयोग करें जिसका उपयोग मैंने अपने लेख में HierarchyID के बारे में किया है। आपको सेल्फ़-जॉइन का उपयोग करके माता-पिता-बच्चे संबंध तालिका में बिना बच्चों वाले नोड्स प्राप्त करने की आवश्यकता है।
SELECT
r1.RankParentId
,r1.Rank AS RankParent
,r.RankId
FROM Ranks r
RIGHT JOIN Ranks r1 ON r.RankParentId = r1.RankId
WHERE r.RankId is NULL
बाहरी जॉइन का उपयोग करने में चेतावनी
चूंकि एक बाहरी जॉइन एक आंतरिक जॉइन की तरह आंतरिक पंक्तियों को वापस कर सकता है, यह भ्रमित कर सकता है। प्रदर्शन समस्याएं भी आ सकती हैं। इसलिए, नीचे दिए गए 3 बिंदुओं पर ध्यान दें (मैं समय-समय पर उनके पास वापस आता हूं - मैं छोटा नहीं हो रहा हूं, इसलिए मैं भी भूल जाता हूं)।
WHERE क्लॉज में एक गैर-शून्य मान के साथ बाएं जॉइन में दायां टेबल फ़िल्टर करना
यह एक समस्या हो सकती है यदि आपने बाएं बाहरी जॉइन का उपयोग किया है लेकिन WHERE क्लॉज में गैर-शून्य मान के साथ सही तालिका फ़िल्टर की है। इसका कारण यह है कि यह कार्यात्मक रूप से इनर जॉइन के समकक्ष हो जाएगा। नीचे दिए गए उदाहरण पर विचार करें:
USE AdventureWorks
GO
SELECT
P.FirstName
,P.MiddleName
,P.LastName
,a.AddressLine1
,a.AddressLine2
,a.City
,adt.Name AS AddressType
FROM Person.Person p
LEFT JOIN Person.BusinessEntityAddress bea ON P.BusinessEntityID = bea.BusinessEntityID
LEFT JOIN Person.Address a ON bea.AddressID = a.AddressID
LEFT JOIN person.AddressType adt ON bea.AddressTypeID = adt.AddressTypeID
WHERE bea.AddressTypeID = 5
ऊपर दिए गए कोड से, आइए 2 तालिकाओं की जांच करें:व्यक्ति और BusinessEntityAddress . व्यक्ति बाईं तालिका है, और BusinessEntityAddress सही तालिका है।
LEFT JOIN का उपयोग किया जाता है, इसलिए यह एक शून्य मान लेता है BusinessEntityID कहीं BusinessEntityAddress . में . यहां, WHERE क्लॉज पर ध्यान दें। यह AddressTypeID . के साथ सही तालिका को फ़िल्टर करता है =5. यह BusinessEntityAddress . में सभी बाहरी पंक्तियों को पूरी तरह से हटा देता है ।
यह इनमें से कोई भी हो सकता है:
- डेवलपर परिणाम में कुछ परीक्षण कर रहा है लेकिन इसे हटाना भूल गया।
- INNER JOIN का इरादा था, लेकिन किसी कारण से, LEFT JOIN का उपयोग किया गया था।
- डेवलपर लेफ्ट जॉइन और इनर जॉइन के बीच के अंतर को नहीं समझता है। वह मानता है कि 2 में से कोई भी काम करेगा, और इससे कोई फर्क नहीं पड़ता क्योंकि इस मामले में परिणाम समान हैं।
उपरोक्त 3 में से कोई भी खराब है, लेकिन तीसरी प्रविष्टि का एक और निहितार्थ है। आइए उपरोक्त कोड की तुलना INNER JOIN समकक्ष से करें:
SELECT
P.FirstName
,P.MiddleName
,P.LastName
,a.AddressLine1
,a.AddressLine2
,a.City
,adt.Name AS AddressType
FROM Person.Person p
INNER JOIN Person.BusinessEntityAddress bea ON P.BusinessEntityID = bea.BusinessEntityID
INNER JOIN Person.Address a ON bea.AddressID = a.AddressID
INNER JOIN person.AddressType adt ON bea.AddressTypeID = adt.AddressTypeID
WHERE bea.AddressTypeID = 5
यह जुड़ने के प्रकार को छोड़कर पिछले कोड के समान दिखता है। परिणाम भी वही है, लेकिन आपको सांख्यिकी IO में तार्किक पठन पर ध्यान देना चाहिए:
चित्र 7 में, पहले I/O आँकड़े INNER JOIN के उपयोग से हैं। कुल तार्किक पठन 177 है। हालाँकि, दूसरे आँकड़े LEFT JOIN के लिए 223 के उच्च तार्किक पठन मान के साथ हैं। इस प्रकार, इस उदाहरण में LEFT JOIN के गलत उपयोग के लिए SQL सर्वर से अधिक पृष्ठों या संसाधनों की आवश्यकता होगी। इसलिए, यह धीमी गति से चलेगी।
टेकअवे
यदि आप आंतरिक पंक्तियों को आउटपुट करना चाहते हैं, तो INNER JOIN का उपयोग करें। अन्यथा, बाएं जॉइन में गैर-शून्य मान के साथ दाएं तालिका को फ़िल्टर न करें। यदि ऐसा होता है, तो आप INNER JOIN का उपयोग करने की तुलना में धीमी क्वेरी के साथ समाप्त होते हैं।
बोनस टिप :यह स्थिति राइट जॉइन में भी होती है जब लेफ्ट टेबल को नॉन-नल वैल्यू के साथ फ़िल्टर किया जाता है।
मल्टी-जॉइन में जॉइन टाइप्स का गलत इस्तेमाल करना
मान लीजिए हम सभी . प्राप्त करना चाहते हैं विक्रेताओं और प्रत्येक के लिए उत्पाद खरीद आदेशों की संख्या। यह रहा कोड:
USE AdventureWorks
GO
SELECT
v.BusinessEntityID
,v.Name AS Vendor
,pod.ProductID
,pod.OrderQty
FROM Purchasing.Vendor v
LEFT JOIN Purchasing.PurchaseOrderHeader poh ON v.BusinessEntityID = poh.VendorID
LEFT JOIN Purchasing.PurchaseOrderDetail pod ON poh.PurchaseOrderID = pod.PurchaseOrderID
उपरोक्त कोड दोनों विक्रेताओं को खरीद आदेश और बिना विक्रेताओं दोनों को लौटाता है। चित्र 8 उपरोक्त कोड की वास्तविक निष्पादन योजना को दर्शाता है।
यह सोचकर कि प्रत्येक खरीद आदेश में एक गारंटीकृत खरीद आदेश विवरण होता है, एक INNER JOIN बेहतर होगा। हालांकि, क्या वाकई ऐसा है?
सबसे पहले, आइए इनर जॉइन के साथ संशोधित कोड लें।
USE AdventureWorks
GO
SELECT
v.BusinessEntityID
,v.Name AS Vendor
,pod.ProductID
,pod.OrderQty
FROM Purchasing.Vendor v
LEFT JOIN Purchasing.PurchaseOrderHeader poh ON v.BusinessEntityID = poh.VendorID
INNER JOIN Purchasing.PurchaseOrderDetail pod ON poh.PurchaseOrderID = pod.PurchaseOrderID
याद रखें, उपरोक्त आवश्यकता "सभी" विक्रेता कहती है। चूंकि हमने पिछले कोड में LEFT JOIN का उपयोग किया था, इसलिए हम विक्रेताओं को बिना खरीद ऑर्डर के वापस कर देंगे। यह शून्य PurchaseOrderID . के कारण है ।
शामिल होने को INNER JOIN में बदलने से सभी शून्य PurchaseOrderIDs निकल जाएंगे। यह सभी शून्य VendorIDs . को भी रद्द कर देगा विक्रेता . से टेबल। असल में, यह एक इनर जॉइन बन जाता है।
क्या यह सही धारणा है? निष्पादन योजना उत्तर प्रकट करेगी:
जैसा कि आप देख सकते हैं, सभी तालिकाओं को INNER JOIN का उपयोग करके संसाधित किया गया था। अतः हमारा अनुमान सही है। लेकिन सबसे बुरी बात यह है कि परिणाम सेट अब गलत है क्योंकि बिना ऑर्डर वाले विक्रेताओं को शामिल नहीं किया गया था।
टेकअवे
पिछले मामले की तरह, यदि आप एक INNER JOIN चाहते हैं, तो इसका उपयोग करें। लेकिन आप जानते हैं कि अगर आपको यहां जैसी स्थिति का सामना करना पड़े तो क्या करना चाहिए।
इस मामले में, एक INNER JOIN संबंध में शीर्ष तालिका तक की सभी बाहरी पंक्तियों को त्याग देगा। भले ही आपका अन्य जॉइन लेफ्ट जॉइन हो, इससे कोई फर्क नहीं पड़ेगा। हमने इसे निष्पादन योजनाओं में साबित कर दिया है।
बाहरी जोड़ में COUNT() का गलत उपयोग
हमारा नमूना कोड याद रखें जो प्रति दिनांक ऑर्डर की संख्या और चित्र 6 में परिणाम की गणना करता है?
यहां, हम स्पष्ट करेंगे कि 02/03/2014 को क्यों हाइलाइट किया गया है और इसका COUNT(soh.OrderDate) से क्या संबंध है ।
यदि आप COUNT(*) का उपयोग करने का प्रयास करते हैं, तो उस तिथि के लिए आदेशों की संख्या 1 हो जाती है, जो गलत है। उस तारीख को कोई आदेश नहीं हैं। इसलिए, बाहरी जॉइन के साथ COUNT() का उपयोग करते समय, गिनने के लिए सही कॉलम का उपयोग करें।
हमारे मामले में, soh.OrderDate शून्य हो सकता है या नहीं। जब यह शून्य नहीं होता है, तो COUNT () में पंक्ति को गिनती में शामिल किया जाएगा। COUNT(*) इसे नल सहित सब कुछ गिन देगा। और अंत में, गलत परिणाम।
आउटर जॉइन टेकअवे
आइए बिंदुओं को संक्षेप में प्रस्तुत करें:
- OUTER JOIN आंतरिक पंक्तियों और बाहरी पंक्तियों दोनों को वापस कर सकता है। आंतरिक पंक्तियाँ परिणाम हैं जो INNER JOIN के परिणाम के समान हैं। बाहरी पंक्तियों में शामिल होने की स्थिति के आधार पर उनके अशक्त समकक्षों के साथ गैर-शून्य मान होते हैं।
- बाहरी जॉइन बाएँ, दाएँ या पूर्ण हो सकते हैं। हमारे पास प्रत्येक के लिए उदाहरण थे।
- OUTER JOIN द्वारा लौटाई गई बाहरी पंक्तियों का उपयोग विभिन्न प्रकार के व्यावहारिक तरीकों से किया जा सकता है। हमारे पास इस बारे में विचार थे कि आप इस सामग्री का उपयोग कब कर सकते हैं।
- बाहरी जॉइन का उपयोग करने में हमारे पास चेतावनी भी थी। बग और प्रदर्शन समस्याओं से बचने के लिए ऊपर दिए गए 3 बिंदुओं का ध्यान रखें।
इस श्रृंखला के अंतिम भाग में क्रॉस जॉइन पर चर्चा होगी। तो, तब तक। और अगर आपको यह पोस्ट पसंद आए तो सोशल मीडिया बटन पर क्लिक करके कुछ प्यार साझा करें। हैप्पी कोडिंग!