JOIN या WHERE के भीतर की स्थिति


192

जोइन क्लॉज बनाम WHERE क्लॉज में कोई शर्त रखने के बीच क्या कोई अंतर (प्रदर्शन, सर्वश्रेष्ठ-अभ्यास, आदि ...) है?

उदाहरण के लिए...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

जो आप पसंद करते हैं (और शायद क्यों)?


4
क्या आपने दो प्रश्नों को चलाया? क्या आपने दो प्रश्नों द्वारा उत्पन्न निष्पादन योजनाओं की जांच की? आपने क्या अवलोकन किया?
एस.लॉट

21
@ S.Lott, यह क्वेरी केवल उदाहरण के लिए है। मैं बस "सामान्य रूप से" सोच रहा हूं जो कि पसंदीदा तरीका है - यदि कोई हो।
स्टीव डिगन

1
@ सिटिव डिग्नन: आपको इसे नमूना डेटा के साथ बेंचमार्क करना चाहिए और क्वेरी योजनाओं को देखना चाहिए। जवाब बहुत, बहुत स्पष्ट होगा। और - बोनस - आपके पास कोड का एक टुकड़ा होगा जब आप अधिक जटिल परिस्थितियां उत्पन्न होने पर पुन: उपयोग कर सकते हैं।
एस.लॉट

1
मैं व्यक्तिगत रूप से स्थिति को जॉइन क्लॉज में रखूंगा यदि शर्त संबंध का वर्णन करती है। सामान्य परिणाम जो केवल परिणाम सेट को फ़िल्टर करते हैं वे तब WHERE भाग में जाते हैं। जैसेFROM Orders JOIN OrderParties ON Orders.Id = OrderParties.Order AND OrderParties.Type = 'Recipient' WHERE Orders.Status = 'Canceled'
Glutexo

जवाबों:


153

संबंधपरक बीजगणित, WHEREखंड और में विधेय के विनिमेयता की अनुमति देता है INNER JOIN, इसलिए खंड के INNER JOINसाथ प्रश्न भी WHEREआशावादी द्वारा पुन: व्यवस्थित किए जा सकते हैं ताकि प्रक्रिया के दौरान उन्हें पहले ही बाहर रखा जाJOIN सके।

मैं आपको सबसे अधिक संभव तरीके से प्रश्नों को लिखने की सलाह देता हूं।

कभी-कभी इसमें INNER JOINअपेक्षाकृत "अधूरा" बनाना और कुछ मानदंडों को WHEREबस आसानी से छानने योग्य मानदंड की सूची बनाना शामिल होता है।

उदाहरण के लिए, इसके बजाय:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

लिखो:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

लेकिन यह निर्भर करता है, निश्चित रूप से।


7
यह केवल स्वच्छ क्वेरी या पठनीयता के बारे में नहीं है, यह प्रदर्शन के बारे में है। ठीक से अनुक्रमित तालिकाओं के साथ बड़ी मात्रा में डेटा के प्रदर्शन में सुधार में शामिल होने की शर्तें।
शहादत

1
मैं सिर्फ मासिक बिक्री रिपोर्ट चलाता हूं जिसमें कुछ लाखों रिकॉर्ड पर 5-6 टेबल शामिल हैं। पर्फ़ 30% तक को बेहतर बनाता है - SQL Server 2012
शहादत

2
@ शहादत अगर आपको वह महत्वपूर्ण अंतर मिल रहा है, जिसमें आपके फ़िल्टर शर्तों को स्थानांतरित किया जा रहा है, जहाँ से क्लॉज़ इनर जॉइन करने के लिए आपको उन निष्पादन योजनाओं को पोस्ट करने की आवश्यकता है।
केड रूक्स

4
@ क्या मैंने निष्पादन योजनाओं की जांच की है - दोनों परिदृश्य समान लागत दिखाते हैं। मैं कई बार प्रश्नों को चलाता हूं लगता है कि दोनों समय के बारे में समान हैं। पहले, मैं उत्पादन पर प्रश्नों को चला रहा था और महत्वपूर्ण प्रदर्शन अंतर मिला क्योंकि डेटाबेस का उपयोग लाइव उपयोगकर्ताओं द्वारा किया जा रहा था। उस भ्रम के लिए क्षमा करें।
शाहदत

4
यह उत्तर INNER JOIN के लिए सही है लेकिन बाएँ / दाएँ जुड़ने के लिए नहीं है।
sotn

121

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

हालाँकि, जहाँ आप शर्त रखते हैं, अगर आप बाएँ या दाएँ जोड़ का उपयोग कर रहे हैं, तो इससे बहुत फर्क पड़ता है। उदाहरण के लिए इन दो प्रश्नों पर विचार करें:

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'

पहला आपको केवल उन्हीं अभिलेखों को देगा जिनके पास 15 मई, 2009 की तुलना में बाद में दिनांकित आदेश है, इस प्रकार बाएं जोड़ को एक आंतरिक जोड़ में परिवर्तित किया गया है। दूसरा उन अभिलेखों को कोई भी ग्राहक देगा, जिनके पास कोई आदेश नहीं होगा। आप जहां शर्त रखते हैं, उसके आधार पर सेट किए गए परिणाम बहुत भिन्न होते हैं। (चयन करें * यदि केवल उदाहरण के उद्देश्यों के लिए, आपको उत्पादन कोड में पाठ्यक्रम का उपयोग नहीं करना चाहिए।) इसका अपवाद तब है जब आप केवल एक तालिका में रिकॉर्ड देखना चाहते हैं, लेकिन दूसरा नहीं। फिर आप इस शर्त का उपयोग करते हैं कि शर्त में शामिल होने के लिए खंड कहां है।

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null

उदाहरणों के साथ समझाने के लिए धन्यवाद
रेनिश जोसेफ

1
"इस प्रकार बाईं ओर को एक आंतरिक जुड़ाव में परिवर्तित करना"। कैसे? क्या आप थोड़ा विस्तार कर सकते हैं?
user1451111

@ user1451111 जानें कि क्या LEFT / RIGHT JOIN रिटर्न: INNER JOIN पंक्तियों के अलावा NULLs द्वारा विस्तारित बाएँ / दाएँ तालिका पंक्तियाँ हैं। फुल जिन्न रिटर्न इनर जॉइन पंक्तियाँ यूनिअन सभी NULLs द्वारा विस्तारित बाएँ और दाएँ तालिका पंक्तियाँ हैं। हमेशा यह जानिए कि INNER JOIN आप एक OUTER JOIN के हिस्से के रूप में क्या चाहते हैं। WHERE या ON के लिए एक NULL- विस्तारित कॉलम की आवश्यकता होती है, जो NULLs द्वारा विस्तारित किसी पंक्तियों को हटाने के बाद NULL न हो, अर्थात केवल INNER JOIN पंक्तियों को छोड़ देता है, अर्थात "INUTER JOIN में OUTER JOIN हो जाता है"।
दार्शनिक

1
@ user1451111 या, सरल शब्दों में: A left join Bए से प्रत्येक पंक्ति बी से प्रत्येक मिलान पंक्ति में शामिल हो गई है। यदि बी में कोई पंक्ति नहीं है जो मेल खाती है, तो ए कॉलम का एक मूल्य है लेकिन उस पंक्ति पर बी से प्रत्येक स्तंभ NULL मान के रूप में दिखाता है। यदि आपने लिखा है where B.somecolumn = ‘somevalue’तो आपके पास 'कुछ' की तुलना में एक NULL (B.somecolumn) है। NULL के साथ तुलना में कुछ भी गलत है, इसलिए आपकी सभी पंक्तियाँ जहाँ A पंक्ति के लिए कोई मिलान B पंक्ति नहीं है, समाप्त हो जाती हैं, और आपके द्वारा प्राप्त परिणाम INNER JOIN के समान होते हैं, इसलिए बाहरी जुड़ाव एक आंतरिक बन गया है
कैयस जार्ड

चयन funds.id, prospects.id से: हाँ मैं जाँच की है परिणामों के लिए ही कर रहे हैं fundsभीतरी पर संभावनाओं में शामिल होने के (prospects.id = funds.lead_id और prospects.is_manual = 'नहीं') और चयन funds.id, prospects.id से fundsबाएं संभावनाओं पर शामिल हों (संभावनाएं ।id = fund.lead_id) जहां संभावनाएं ।is_manual = 'नहीं'
रोहित धीमान

25

अधिकांश RDBMS उत्पाद दोनों प्रश्नों को समान रूप से अनुकूलित करेंगे। पीटर गुल्त्ज़न और ट्रुडी पेल्ज़र द्वारा "एसक्यूएल प्रदर्शन ट्यूनिंग" में, उन्होंने आरडीबीएमएस के कई ब्रांडों का परीक्षण किया और कोई प्रदर्शन अंतर नहीं पाया।

मैं क्वेरी प्रतिबंध स्थितियों से अलग होने वाली शर्तों को रखना पसंद करता हूं।

यदि आप OUTER JOINकभी-कभी उपयोग कर रहे हैं तो ज्वाइन क्लॉज में शर्तें लगाना आवश्यक है।


1
मैं आपसे सहमत हूं कि वाक्य-रचना में यह साफ-सुथरा है, और मुझे उस पुस्तक के बारे में और आपकी बहुत उच्च प्रतिष्ठा के बारे में जानकारी प्राप्त करनी है, लेकिन मैं अंतिम सप्ताह में बहुत ही अलग निष्पादन योजनाओं, सीपीयू समय, और तार्किक पढ़ता है मैं जहां स्थानांतरित होने के लिए भविष्यवाणी करता हूं, वहां चला गया।
marr75

2
आप सर्वोत्तम प्रथाओं के बारे में पूछ रहे थे। जैसे ही आप परीक्षण करते हैं कि एक विशिष्ट RDBMS कार्यान्वयन कैसे काम करता है, अन्य लोगों ने सही सलाह दी है: बेंचमार्क।
बिल करविन

12

जॉइन होने के बाद जहां फिल्टर होगा।

JOIN प्रक्रिया के दौरान पंक्तियों को जोड़ने से रोकने के लिए JOIN पर फ़िल्टर करें।


10
शब्दार्थ रूप से, उन्हें INNER JOIN प्रक्रिया के दौरान रोका जाता है, लेकिन ऑप्टिमाइज़र INNER JOIN को पुन: व्यवस्थित कर सकता है और जहाँ पर इच्छाशक्ति की भविष्यवाणी करता है, इसलिए ऑप्टिमाइज़र बाद में उन्हें बाहर करने के लिए स्वतंत्र होता है यदि वह चाहे तो।
केड रूक्स

1
कैड रूक्स: राइट। अक्सर जब आप एसक्यूएल में लिखते हैं तो वह नहीं होता है, जब आशावादी आपको वह सब देगा, जो किया जाता है। मुझे लगता है कि यह एक सर्व-सिद्धांत दुनिया में सही होगा, जबकि आपका जवाब स्वचालित क्वेरी ऑप्टिमाइज़र की दुनिया में अधिक सही है :)
TheTXI

मुझे हालत की यह व्याख्या पसंद हैON
रॉबर्ट रोचा

3

मैं पूरी तालिका / दृश्य में शामिल होने के लिए JOIN पसंद करता हूं और फिर परिणामी सेट की विधेय को शुरू करने के लिए WHERE का उपयोग करता हूं।

यह सिंथेटिक रूप से क्लीनर महसूस करता है।


2

मैं आमतौर पर प्रदर्शन में वृद्धि को देखता हूं जब शामिल होने पर फ़िल्टरिंग करता है। खासकर यदि आप दोनों तालिकाओं के लिए अनुक्रमित स्तंभों पर शामिल हो सकते हैं। आपको तार्किक रीडर्स पर कटौती करने में सक्षम होना चाहिए, ऐसा करने वाले अधिकांश प्रश्नों के साथ, जो कि उच्च मात्रा वाले वातावरण में, निष्पादन समय की तुलना में बहुत बेहतर प्रदर्शन संकेतक है।

जब मैं किसी को अपनी SQL बेंचमार्किंग दिखाता हूं, तो मैं हमेशा हल्के-फुल्के अंदाज में होता हूं और उन्होंने आधी रात को देव सर्वर पर 50,000 बार के दोनों संस्करणों को अंजाम दिया है और औसत समय की तुलना करते हैं।


0

इस शर्त में शामिल होने से मुझे "शब्द" गलत लगता है, क्योंकि जोइन "के लिए" नहीं हैं। लेकिन यह बहुत गुणात्मक है।

अतिरिक्त समस्या: यदि आप एक आंतरिक जॉइन से स्विच करने का निर्णय लेते हैं, तो कहते हैं, एक सही जॉइन, जोइन के अंदर की स्थिति होने से अप्रत्याशित परिणाम हो सकते हैं।


3
कभी-कभी ये परिणाम थोड़े "अपेक्षित" होते हैं और कभी-कभी "जानबूझकर" भी होते हैं (उदाहरण के लिए बाहरी जोड़ के साथ, जहां WHER की स्थिति में JOIN स्थिति से अलग शब्दार्थ है)।
मार्सेल टूथ

0

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


-4

जॉइन में कंडीशन जोड़ना बेहतर है। पठनीयता की तुलना में प्रदर्शन अधिक महत्वपूर्ण है। बड़े डेटासेट के लिए, यह मायने रखता है।


1
क्या आपके पास किसी प्रकार का प्रमाण है, शोध है कि उल्लेखित विधेय की नियुक्ति प्रदर्शन को कैसे प्रभावित करती है?
10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.