SQL बाईं ओर से FROM लाइन पर कई तालिकाओं में शामिल हो गया?


256

अधिकांश SQL बोलियाँ निम्नलिखित दोनों प्रश्नों को स्वीकार करती हैं:

SELECT a.foo, b.foo
FROM a, b
WHERE a.x = b.x

SELECT a.foo, b.foo
FROM a
LEFT JOIN b ON a.x = b.x

अब स्पष्ट रूप से जब आपको बाहरी जुड़ाव की आवश्यकता होती है, तो दूसरे सिंटैक्स की आवश्यकता होती है। लेकिन जब एक आंतरिक शामिल हो रहा है तो मुझे पहले (या इसके विपरीत) के लिए दूसरा वाक्यविन्यास क्यों पसंद करना चाहिए?


1
गुफ़ा: आपको यह कैसे पता चला? यद्यपि मेरा प्रश्न "मैं कैसे करूँ" की तुलना में सबसे अच्छा अभ्यास है
jmucchiello

चूंकि यह सबसे अच्छा अभ्यास है, कृपया इसे विकी बनाएं।
बिन्नोज एंटनी

1
मुझे नहीं लगता कि इन दोनों के प्रदर्शन के बारे में किसी ने टिप्पणी की है। क्या कोई किसी भी महत्वपूर्ण अंतर के बारे में किसी भी बात की पुष्टि या हवाला दे सकता है?
अहानिबेकाड

@ahnbizcad दो दिए गए प्रश्न एक ही काम नहीं करते हैं। पहला INNER JOIN ON के समान है। कार्यान्वयन DBMS संस्करण-विशिष्ट है, और तब भी कुछ गारंटी है। लेकिन DBMS ट्रांसफॉर्मेशन के मामले कमिंग बनाम INNER JOIN ON / WHERE vs CROSS JOIN WHERE तुच्छ है। रिलेशनल डेटाबेस क्वेरी ऑप्टिमाइज़ेशन / कार्यान्वयन के बारे में जानें।
फिलीपिसे

संसाधन की सिफारिश मिली? विशाल, घने मैनुअल हैं, इसलिए मैं यहां से सीखने की कोशिश करता हूं।
एहनबीकैड

जवाबों:


319

पुराने सिंटैक्स, तालिकाओं को सूचीबद्ध करने, और WHEREशामिल होने के मानदंडों को निर्दिष्ट करने के लिए क्लॉज का उपयोग करते हुए , अधिकांश आधुनिक डेटाबेस में चित्रित किया जा रहा है।

यह केवल दिखाने के लिए नहीं है, पुराने वाक्यविन्यास में अस्पष्ट होने की संभावना है जब आप एक ही क्वेरी में INNER और OUTER दोनों का उपयोग करते हैं।

मैं आपको एक उदाहरण देता हूं।

मान लीजिए कि आपके सिस्टम में 3 टेबल हैं:

Company
Department
Employee

प्रत्येक तालिका में कई पंक्तियाँ होती हैं, जो एक साथ जुड़ी होती हैं। आपको कई कंपनियां मिलीं, और प्रत्येक कंपनी में कई विभाग हो सकते हैं, और प्रत्येक विभाग में कई कर्मचारी हो सकते हैं।

ठीक है, तो अब आप निम्नलिखित करना चाहते हैं:

सभी कंपनियों को सूचीबद्ध करें, और उनके सभी विभागों, और उनके सभी कर्मचारियों को शामिल करें। ध्यान दें कि कुछ कंपनियों के पास अभी तक कोई विभाग नहीं है, लेकिन सुनिश्चित करें कि आप उन्हें भी शामिल करें। सुनिश्चित करें कि आप केवल उन विभागों को पुनः प्राप्त करते हैं जिनके पास कर्मचारी हैं, लेकिन हमेशा सभी कंपनियों को सूचीबद्ध करें।

तो आप ऐसा करें:

SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
  AND Department.ID = Employee.DepartmentID

ध्यान दें कि अंतिम एक आंतरिक जुड़ाव है, जो कि उन मानदंडों को पूरा करने के लिए है जो आप केवल लोगों के साथ विभाग चाहते हैं।

ठीक है, तो अब क्या होता है। खैर, समस्या यह है, यह डेटाबेस इंजन, क्वेरी ऑप्टिमाइज़र, इंडेक्स और टेबल सांख्यिकी पर निर्भर करता है। मुझे समझाने दो।

यदि क्वेरी ऑप्टिमाइज़र यह निर्धारित करता है कि ऐसा करने का तरीका पहले एक कंपनी लेना है, तो विभागों को ढूंढें, और फिर कर्मचारियों के साथ एक आंतरिक जुड़ाव करें, आपको कोई भी ऐसी कंपनी नहीं मिलने वाली है जिसके पास विभाग नहीं हैं।

इसका कारण यह है कि WHEREखंड यह निर्धारित करता है कि कौन से पंक्तियाँ अंतिम परिणाम में समाप्त होती हैं , न कि पंक्तियों के अलग-अलग हिस्सों में।

और इस मामले में, बाईं ओर शामिल होने के कारण, विभाग .ID कॉलम NULL होगा, और इस प्रकार जब यह कर्मचारी के लिए ININ JOIN की बात आती है, तो कर्मचारी पंक्ति के लिए उस बाधा को पूरा करने का कोई तरीका नहीं है, और इसलिए यह नहीं है दिखाई देते हैं।

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

तो पुराना वाक्यविन्यास अस्पष्ट है। क्वेरी संकेत से निपटने के बिना, आप क्या चाहते हैं, यह निर्दिष्ट करने का कोई तरीका नहीं है और कुछ डेटाबेस में कोई रास्ता नहीं है।

नया सिंटैक्स दर्ज करें, इसके साथ आप चुन सकते हैं।

उदाहरण के लिए, यदि आप सभी कंपनियों को चाहते हैं, जैसा कि समस्या विवरण में कहा गया है, तो यह वही है जो आप लिखेंगे:

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID

यहां आप यह निर्दिष्ट करते हैं कि आप चाहते हैं कि विभाग-कर्मचारी जुड़कर एक के रूप में किया जाए, और फिर कंपनियों के साथ उस के परिणामों में शामिल हों।

इसके अतिरिक्त, मान लें कि आप केवल ऐसे विभाग चाहते हैं जिनमें उनके नाम के अक्षर X हों। फिर से, पुरानी शैली के साथ जुड़ने पर, आप कंपनी को खोने का जोखिम उठाते हैं, अगर उसके नाम में X के साथ कोई विभाग नहीं है, लेकिन नए सिंटैक्स के साथ, आप यह कर सकते हैं:

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'

यह अतिरिक्त खंड जुड़ने के लिए उपयोग किया जाता है, लेकिन पूरी पंक्ति के लिए फ़िल्टर नहीं है। तो पंक्ति कंपनी की जानकारी के साथ दिखाई दे सकती है, लेकिन उस पंक्ति के लिए सभी विभाग और कर्मचारी कॉलम में NULL हो सकते हैं, क्योंकि उस कंपनी के लिए उसके नाम में X के साथ कोई विभाग नहीं है। पुराने सिंटेक्स के साथ यह कठिन है।

यही कारण है कि, अन्य विक्रेताओं के बीच, Microsoft ने SQL सर्वर 2005 और उसके बाद के पुराने पुराने सम्मिलित वाक्य-विन्यास को नहीं, बल्कि पुराने आंतरिक सम्मिलित वाक्य-विन्यास को चित्रित किया है। Microsoft SQL Server 2005 या 2008 पर चल रहे डेटाबेस से बात करने का एकमात्र तरीका पुरानी शैली के बाहरी सिंटैक्स का उपयोग करके, उस डेटाबेस को 8.0 संगतता मोड (उर्फ SQL सर्वर 2000) में सेट करना है।

इसके अतिरिक्त, पुराने तरीके, क्वेरी ऑप्टिमाइज़र पर तालिकाओं का एक गुच्छा फेंककर, जहां WHERE क्लॉज़ के एक समूह के साथ, "आप यहाँ हैं, सबसे अच्छा आप कर सकते हैं" कहने के लिए समान था। नए सिंटैक्स के साथ, क्वेरी ऑप्टिमाइज़र के पास यह जानने के लिए कम काम होता है कि कौन से भाग एक साथ चलते हैं।

इसलिए यह अब आपके पास है।

LEFT और INNER JOIN भविष्य की लहर है।


28
"अधिकांश आधुनिक डेटाबेस में पदावनत किया जा रहा है।" --- बस जिज्ञासु, कौन सा?
झटके

10
मुझे माफ कर दो, मैं * = ऑपरेटर से परिचित नहीं हूं, यह क्या करता है? धन्यवाद!
अल्ट्रोज़ोन

9
स्टार = और = स्टार (अच्छी तरह से) दाएं और बाएं बाहरी जोड़ थे, या क्या वह बाएं और दाएं है? उम्र के लिए पदावनत किया गया, मैंने उन्हें SQL Server 6. के बाद से उपयोग नहीं किया है
टोनी हॉपकिंसन

3
कोम्मा को पदावनत नहीं किया जाता है। कभी-भी मानक OUTER JOINवाक्यविन्यास *=/ =*/ *=*को घटाया नहीं जाता है।
फिलीपिक्सी

1
यह जवाब सवाल का जवाब भी नहीं देता है, जो बाहरी जुड़ाव के बारे में नहीं है। यह जो दावा करता है कि यह कॉमा बनाम INNER JOIN ON, पुनः अनुकूलन के बारे में है, गलत है।
दार्शनिक

17

जोइन सिंटैक्स वे लागू होने वाली तालिका के पास स्थितियां रखता है। यह विशेष रूप से उपयोगी है जब आप बड़ी मात्रा में तालिकाओं में शामिल होते हैं।

वैसे, आप पहले वाक्य रचना के साथ एक बाहरी जुड़ाव भी कर सकते हैं:

WHERE a.x = b.x(+)

या

WHERE a.x *= b.x

या

WHERE a.x = b.x or a.x not in (select x from b)

2
MS SQLServer में * = सिंटैक्स को घटाया जाता है और अच्छे कारण के लिए: न केवल इसे पढ़ने में मुश्किल होती है, लेकिन यह ऐसा नहीं करता है जो लोग सोचते हैं कि यह करता है और यह एक समान रूप से देखने वाले LEFT JOIN के समान नहीं है। (+) वाक्य-विन्यास मेरे लिए अपरिचित है; SQL कार्यान्वयन क्या करता है?
यूरो माइकेल

2
अन्य सिंटैक्स का उपयोग Oracle द्वारा किया जाता है, कम से कम।
लास वी। कार्लसन

4
एसक्यूएल सर्वर सिंटैक्स * का उपयोग कभी न करें, यह लगातार परिणाम नहीं देगा क्योंकि यह कभी-कभी एक क्रॉस जॉइन के रूप में व्याख्या करेगा जो एक लेफ्ट जॉइन नहीं है। यह SQL Server 2000 के रूप में भी वापस सत्य है। यदि आपके पास इसका उपयोग करने वाला कोई कोड है, तो आपको इसे ठीक करने की आवश्यकता है।
HLGEM

12

पहला तरीका पुराना मानक है। दूसरी विधि SQL-92, http://en.wikipedia.org/wiki/SQL में शुरू की गई थी । पूरा मानक http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt पर देखा जा सकता है ।

डेटाबेस कंपनियों द्वारा SQL-92 मानक को अपनाने में कई साल लग गए।

तो दूसरी विधि को पसंद करने का कारण, यह ANSI और ISO मानक समिति के अनुसार SQL मानक है।


,अभी भी मानक है। onकेवल outer joinएक बार subselects शुरू करने के लिए शुरू किए जाने की जरूरत है ।
फिलीपिक्सी

12

मूल रूप से, जब आपका FROM क्लॉज़ टेबल को इस तरह सूचीबद्ध करता है:

SELECT * FROM
  tableA, tableB, tableC

परिणाम तालिका ए, बी, सी में सभी पंक्तियों का एक क्रॉस उत्पाद है। फिर आप प्रतिबंध लागू करते हैं WHERE tableA.id = tableB.a_idजो बड़ी संख्या में पंक्तियों को फेंक देगा, फिर आगे ... AND tableB.id = tableC.b_idऔर आपको केवल उन पंक्तियों को प्राप्त करना चाहिए जिन्हें आप वास्तव में रुचि रखते हैं में।

DBMSs जानते हैं कि इस SQL ​​को कैसे ऑप्टिमाइज़ किया जाए ताकि JOINs का उपयोग करके इसे लिखने का प्रदर्शन अंतर नगण्य हो (यदि कोई हो)। जॉइन नोटेशन का उपयोग एसक्यूएल स्टेटमेंट को अधिक पठनीय बनाता है (आईएमएचओ, जॉइन का उपयोग नहीं करने से स्टेटमेंट गड़बड़ हो जाता है)। क्रॉस उत्पाद का उपयोग करके, आपको WHERE क्लॉज़ में शामिल होने के मापदंड प्रदान करने की आवश्यकता है, और यह नोटेशन के साथ समस्या है। आप इस तरह के सामान के साथ अपने WHERE क्लॉज की भीड़ कर रहे हैं

    tableA.id = tableB.a_id 
AND tableB.id = tableC.b_id 

जिसका उपयोग केवल क्रॉस उत्पाद को प्रतिबंधित करने के लिए किया जाता है। जहां क्लॉज में परिणाम के लिए केवल अनुपात होना चाहिए। यदि आप तालिका को परिणाम के प्रतिबंधों के साथ मिलाते हैं, तो आप (और अन्य) आपकी क्वेरी को पढ़ने में कठिन पाएंगे। आपको निश्चित रूप से JOINs का उपयोग करना चाहिए और FROM क्लॉज को FROM क्लॉज पर रखना चाहिए, और WHERE क्लॉज को WHERE क्लॉज करना चाहिए।


10

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

इसके अतिरिक्त जब आपको बाद में लेफ्ट जॉइन करना होता है, तो यह रखरखाव के लिए सहायक होता है कि वे सभी एक ही संरचना में हों। और पुराना सिंटैक्स 1992 से पुराना है, इसका उपयोग बंद करने का अच्छा समय है।

इसके अलावा मैंने पाया है कि कई लोग जो विशेष रूप से पहले वाक्यविन्यास का उपयोग करते हैं, वे वास्तव में जुड़ाव को नहीं समझते हैं और जुड़ने को समझने के लिए महत्वपूर्ण है कि क्वेरी करते समय सही परिणाम प्राप्त करना महत्वपूर्ण है।


6

मुझे लगता है कि इस पद्धति पर कुछ अच्छे कारण हैं जो दूसरी विधि-प्रयोग करने वाली स्पष्ट जॉइन को अपनाने के लिए हैं। हालांकि यह है कि जब WH मान खंड से JOIN मानदंड हटा दिए जाते हैं, तो यह होता है कि WHERE खंड में शेष चयन मानदंड देखना अधिक आसान हो जाता है।

वास्तव में जटिल सेलेक्ट स्टेटमेंट में एक पाठक के लिए यह समझना बहुत आसान हो जाता है कि क्या हो रहा है।


5

SELECT * FROM table1, table2, ...वाक्य रचना टेबल के एक जोड़े के लिए ठीक है, लेकिन यह (तेजी से हो जाता है जरूरी नहीं कि एक गणितीय सटीक बयान ) कठिन है और कठिन तालिकाओं की संख्या बढ़ जाती के रूप में पढ़ने के लिए।

JOIN सिंटैक्स लिखना (शुरुआत में) कठिन है, लेकिन यह स्पष्ट करता है कि कौन सी तालिका किन मानदंडों को प्रभावित करती है। इससे गलती करने में बहुत मुश्किल होती है।

इसके अलावा, यदि सभी जोड़ INNER हैं, तो दोनों संस्करण समान हैं। हालाँकि, जिस समय आपके पास एक OUTER होता है, वह कहीं भी बयान में शामिल हो जाता है, चीजें बहुत अधिक जटिल हो जाती हैं और यह वस्तुतः गारंटी है कि आप जो लिखते हैं वह आपके द्वारा लिखे गए विचार के अनुसार क्वेरी नहीं होगा।


2

जब आपको बाहरी की जरूरत होती है तो दूसरा सिंटैक्स शामिल नहीं होता है आवश्यकता होती है:

आकाशवाणी:

SELECT a.foo, b.foo
  FROM a, b
 WHERE a.x = b.x(+)

MSSQLServer (हालाँकि इसे 2000 संस्करण में हटा दिया गया है) / साइबेस:

SELECT a.foo, b.foo
  FROM a, b
 WHERE a.x *= b.x

लेकिन अपने सवाल पर लौटते हुए। मैं जवाब पता नहीं है, लेकिन यह शायद इस तथ्य एक से संबंधित है में शामिल होने के एक करने के लिए एक अभिव्यक्ति जोड़ने से अधिक स्वाभाविक है (वाक्य रचना, कम से कम) जहां : खंड जब आप वास्तव में क्या कर रहे हैं में शामिल होने


SQL सर्वर ने यह दर्शाया है कि बाएँ वाक्य रचना में शामिल हैं और यहां तक ​​कि SQL सर्वर 2000 में भी यह लगातार सही परिणाम नहीं देगा (कभी-कभी यह बाईं ओर के बजाय एक क्रॉस जॉइन करता है) और SQL सर्वर में कभी भी उपयोग नहीं किया जाना चाहिए।
HLGEM

@HLGEM: जानकारी के लिए धन्यवाद। मैं अपनी पोस्ट को दिखाने के लिए अद्यतन करने जा रहा हूं कि आप क्या कह रहे हैं।
पाब्लो सांता क्रूज़

0

मैंने सुना है बहुत से लोग शिकायत करते हैं कि पहला समझना बहुत मुश्किल है और यह स्पष्ट नहीं है। मुझे इसके साथ कोई समस्या नहीं दिख रही है, लेकिन उस चर्चा के बाद, मैं स्पष्टता के लिए INNER JOINS पर भी दूसरा प्रयोग करता हूं।


1
मुझे जॉय सिंटैक्स का उपयोग न करने और इसे पहले तरीके से करने की आदत के साथ लाया गया था। मुझे स्वीकार करना चाहिए कि मैं अभी भी अक्सर इस आदत में फंस जाता हूं क्योंकि मुझे लगता है कि मेरे दिमाग को उस तर्क का पालन करने के लिए वातानुकूलित किया गया है, जो समय के साथ वाक्यविन्यास में शामिल हो जाता है, मुझे लगता है कि कठिन लगता है।
TheTXI

3
मुझे भी यही तरीका सिखाया गया था। मैंने अपनी कोडिंग शैली बदल दी, क्योंकि लोग इसे देखेंगे और आसानी से पहचान नहीं पाएंगे कि क्या चल रहा था। चूंकि कोई तार्किक अंतर नहीं है और मैं बाद में पूर्व को चुनने का कोई कारण नहीं पा सकता हूं, इसलिए मुझे लगा कि मुझे दूसरों को समझने में मदद करने के लिए कोड को स्पष्ट करने के लिए अनुकूलित करना चाहिए।
kemiller2002

0

डेटाबेस के लिए, वे एक ही होने का अंत करते हैं। आपके लिए, हालांकि, आपको कुछ स्थितियों में उस दूसरे सिंटैक्स का उपयोग करना होगा। संपादन प्रश्नों के लिए, जो इसे उपयोग करने के लिए समाप्त हो गए हैं (यह पता लगाना कि आपको एक बाएं ज्वाइन की जरूरत है, जहां आप सीधे शामिल हुए थे), और स्थिरता के लिए, मैं केवल 2 विधि पर पैटर्न करूंगा। यह प्रश्नों को पढ़ना आसान बना देगा।


0

वैसे पहले और दूसरे प्रश्नों में अलग-अलग परिणाम हो सकते हैं क्योंकि एक LEFT JOIN में पहली तालिका से सभी रिकॉर्ड शामिल हैं, भले ही सही तालिका में कोई रिकॉर्ड न हों।

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