एसक्यूएल जॉइन - जहां क्लॉज बनाम क्लॉज है


688

इसे पढ़ने के बाद, यह स्पष्ट बनाम नकली SQL जॉइन का डुप्लिकेट नहीं है । उत्तर संबंधित हो सकता है (या समान भी) लेकिन सवाल अलग है।


क्या अंतर है और प्रत्येक में क्या जाना चाहिए?

यदि मैं सिद्धांत को सही ढंग से समझता हूं, तो क्वेरी ऑप्टिमाइज़र को दोनों को एक दूसरे के साथ उपयोग करने में सक्षम होना चाहिए।


2
बस भविष्य के पाठकों और आपकी जानकारी के लिए आपको sql निष्पादन का क्रम पढ़ना चाहिए। इससे आपको अंतर्निहित अंतर को समझने में अधिक सटीक मदद मिलेगी।
राहुल नीखरा

जवाबों:


870

ये एक ही चीज नहीं हैं।

इन प्रश्नों पर विचार करें:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

तथा

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

पहला ऑर्डर क्रमांक के लिए एक ऑर्डर और उसकी लाइनें, यदि कोई हो, वापस करेगा 12345। दूसरा सभी आदेश वापस कर देगा, लेकिन केवल आदेश में 12345इसके साथ कोई भी लाइनें जुड़ी होंगी।

INNER JOINए के साथ , क्लॉज प्रभावी रूप से समकक्ष हैं। हालांकि, सिर्फ इसलिए कि वे कार्यात्मक रूप से समान हैं, इसमें वे एक ही परिणाम उत्पन्न करते हैं, इसका मतलब यह नहीं है कि दो प्रकार के खंडों का अर्थ समान अर्थ है।


83
क्या आप इनर जॉइन के लिए "ऑन" क्लॉज में कहां क्लॉज लगाकर बेहतर प्रदर्शन प्राप्त करेंगे?
FistOfFury

96
@FistOfFury Sql सर्वर एक क्वेरी ऑप्टिमाइज़र प्रक्रिया का उपयोग करता है जो आपके कोड को सबसे अच्छा निष्पादन योजना का उत्पादन करने के लिए संकलित और मूल्यांकन करता है। यह सही नहीं है, लेकिन ज्यादातर समय यह मायने नहीं रखेगा और आपको उसी तरह से निष्पादन योजना मिलेगी।
जोएल कोएहॉर्न

18
पोस्टग्रेज में मैंने नोट किया कि वे समान नहीं थे और परिणामस्वरूप अलग-अलग क्वेरी प्लान थे। यदि आप ON का उपयोग करते हैं, तो यह भौतिक के उपयोग के परिणामस्वरूप हुआ। यदि आपने WHERE का उपयोग किया है, तो इसने हैश का उपयोग किया है। मटीरियल में बदतर मामला था जो हैश की तुलना में 10 गुना अधिक महंगा था। यह एकल ID के बजाय ID के सेट का उपयोग कर रहा था।
जेम्स हचिसन

13
@JamesHutchison इस तरह से देखे गए व्यवहार के आधार पर विश्वसनीय प्रदर्शन सामान्यीकरण करना कठिन है। एक दिन जो सच था वह आगे गलत हो जाता है, क्योंकि यह दस्तावेजी व्यवहार के बजाय कार्यान्वयन विवरण है। डेटाबेस टीमें हमेशा ऑप्टिमाइज़र प्रदर्शन को बेहतर बनाने के लिए स्थानों की तलाश में रहती हैं। मुझे आश्चर्य होगा अगर ON व्यवहार WHERE से मेल खाने के लिए नहीं सुधरा। यह सामान्य प्रदर्शन सुधार जैसे कुछ के अलावा संस्करण से संस्करण में जारी नोटों में कहीं भी दिखाई नहीं दे सकता है।
जोएल कोएहॉर्न

4
@ TFHoran यह नहीं है कि Sql सर्वर कैसे काम करता है। यह एग्रेसिवली प्री-फिल्टर होगा जहां WHERE क्लॉज के आइटम पर आधारित होगा जब आंकड़े दिखाते हैं कि यह मददगार हो सकता है।
जोएल कोएहॉर्न

362
  • भीतर के जुड़ाव के लिए कोई फर्क नहीं पड़ता
  • बाहरी जुड़ाव के लिए मामले

    ए। WHEREक्लॉज: ज्वाइन करने के बाद । इसमें शामिल होने के बाद रिकॉर्ड को फ़िल्टर किया जाएगा।

    ख। ONक्लॉज - जॉइन करने से पहले। शामिल होने से पहले रिकॉर्ड (दाएं टेबल से) फ़िल्टर किया जाएगा। यह परिणाम में शून्य के रूप में समाप्त हो सकता है (जब से OUTER सम्मिलित हों)।



उदाहरण : नीचे दी गई तालिकाओं पर विचार करें:

    1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

क) अंदर का WHEREखंड:

  SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  | 

b) JOINक्लॉज के अंदर

  SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL | 

40
IMO यह सबसे अच्छा जवाब है क्योंकि यह स्पष्ट रूप से दर्शाता है कि अन्य लोकप्रिय उत्तरों के 'हुड के नीचे' क्या चल रहा है।
Psrpsrpsr

1
बहुत बढ़िया स्पष्टीकरण .... अच्छा किया! - बस जिज्ञासु कि आपने इसे पाने के लिए क्या किया intermediate join table? कुछ 'व्याख्या' आदेश?
मैनुअल जॉर्डन

1
@ मैनुएलजॉर्डन नहीं, यह केवल स्पष्टीकरण के लिए है। एक डेटाबेस एक मध्यवर्ती तालिका बनाने की तुलना में कुछ अधिक प्रदर्शन कर सकता है।
संदीप जिंदल

समझ में आया, मैंने मान लिया कि शायद एक तीसरे उपकरण का उपयोग किया गया था।
मैनुअल जॉर्डन

145

पर INNER JOINरों वे परस्पर विनिमय कर रहे हैं, और अनुकूलक उन्हें अपनी इच्छा से पुन: व्यवस्थित होगा।

पर OUTER JOINहै, वे पर की जो पक्ष में शामिल होने वे पर निर्भर आधार पर जरूरी परस्पर विनिमय नहीं कर रहे हैं।

मैंने उन्हें पठनीयता के आधार पर किसी भी स्थान पर रखा।



यह संभवतः क्लॉज़ में एक बहुत स्पष्ट है, विशेष रूप से Orders.Join( OrderLines, x => x.ID, x => OrderID, (o,l) => new {Orders = o, Lines = l}).Where( ol => ol.Orders.ID = 12345)
लिनक

49

जिस तरह से मैं यह कर रहा हूँ:

  • ONयदि आप कर रहे हैं तो हमेशा जॉइन की शर्तों को क्लॉज में रखें INNER JOIN। इसलिए, ON क्लाज पर कोई भी शर्त न जोड़ें, उन्हें WHEREक्लॉज में रखें।

  • यदि आप एक कर रहे हैं LEFT JOIN, तो किसी भी WHERE शर्तों को शामिल होने ONके दाईं ओर तालिका के लिए खंड में जोड़ें । यह एक जरूरी है, क्योंकि WHERE क्लॉज जोड़ने से जो जुड़ने के दाईं ओर सन्दर्भ देता है, वह Join को INNER JOIN में बदल देगा।

    अपवाद तब है जब आप उन रिकॉर्डों की तलाश कर रहे हैं जो किसी विशेष तालिका में नहीं हैं। आप राइट यूनीक आइडेंटिफायर (जो कि कभी NULL नहीं है) के संदर्भ में जोड़ेंगे जहां इस तरह से क्लॉज करें WHERE t2.idfield IS NULL। तो, केवल एक बार जब आपको शामिल होने के दाईं ओर एक तालिका का संदर्भ देना चाहिए, तो उन रिकॉर्डों को खोजना होगा जो तालिका में नहीं हैं।


8
इस पर मैंने अब तक पढ़ा सबसे अच्छा जवाब है। पूरी तरह से समझ में आता है कि एक बार जब आपका मस्तिष्क एक लेफ्ट जॉइन को समझता है तो लेफ्ट टेबल में सभी पंक्तियों को वापस करने जा रहा है और आपको इसे बाद में फ़िल्टर करना होगा।
निक लार्सन

यदि आप बाहरी रूप से एक अशक्त स्तंभ के साथ एक तालिका में शामिल होते हैं, तो आप अभी भी "जहां" उस स्तंभ को बिना एक आंतरिक जोड़ के "अशक्त" कर सकते हैं? यह वास्तव में उन अभिलेखों की तलाश नहीं है जो केवल एक विशेष तालिका में नहीं हैं। आप 1 के लिए देख सकते हैं। अस्तित्व में नहीं है 2. बिल्कुल भी मूल्य नहीं है।
पास

मेरा मतलब है कि आप दोनों की तलाश कर सकते हैं: "1. अस्तित्व में नहीं है। 2. एक साथ मूल्य नहीं है"। और यह उस स्थिति पर लागू होता है जहां वह क्षेत्र आइडियल नहीं है।
पास

जैसा कि मैंने इस मामले का सामना किया: एक आपातकालीन संपर्क के बिना नए सिरे से डेटा (अभी तक इनपुट नहीं किया गया) सहित प्रतिभागियों की तलाश।
पास

30

एक आंतरिक जुड़ाव पर, उनका मतलब वही है। हालाँकि आपको बाहरी परिणाम में अलग-अलग परिणाम मिलेंगे, जो इस बात पर निर्भर करता है कि आप ज्वाइन की शर्त को WHERE vs ON क्लॉज में रखते हैं या नहीं। इस संबंधित प्रश्न और इस उत्तर (मेरे द्वारा) पर एक नज़र डालें ।

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


26

यह एक बहुत ही सामान्य प्रश्न है, इसलिए यह उत्तर मेरे द्वारा लिखे गए इस लेख पर आधारित है ।

टेबल रिलेशनशिप

निम्नलिखित postऔर post_commentतालिकाओं को ध्यान में रखते हुए :

<कोड> पोस्ट </ कोड> और <कोड> पोस्ट_कॉममेंट </ कोड> टेबल

postनिम्नलिखित रिकॉर्ड है:

| id | title     |
|----|-----------|
| 1  | Java      |
| 2  | Hibernate |
| 3  | JPA       |

और post_commentनिम्नलिखित तीन पंक्तियाँ हैं:

| id | review    | post_id |
|----|-----------|---------|
| 1  | Good      | 1       |
| 2  | Excellent | 1       |
| 3  | Awesome   | 2       |

SQL INNER JOIN करें

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

जबकि CROSS JOIN कुछ परिदृश्यों में उपयोगी है, अधिकांश समय, आप एक विशिष्ट स्थिति के आधार पर तालिकाओं में शामिल होना चाहते हैं। और, यह वह जगह है जहाँ INNER JOIN खेल में आता है।

SQL INNER JOIN हमें एक शर्त के आधार पर दो तालिकाओं के जुड़ने के कार्टेशियन उत्पाद को फ़िल्टर करने की अनुमति देता है, जो ON क्लॉज़ के माध्यम से निर्दिष्ट होता है।

SQL INNER JOIN - "हमेशा सही" स्थिति पर

यदि आप एक "हमेशा सत्य" स्थिति प्रदान करते हैं, तो INNER JOIN सम्मिलित रिकॉर्ड्स को फ़िल्टर नहीं करेगा, और परिणाम सेट में दो सम्मिलित तालिकाओं के कार्टेशियन उत्पाद शामिल होंगे।

उदाहरण के लिए, यदि हम निम्नलिखित SQL INNER JOIN क्वेरी को निष्पादित करते हैं:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1

हम postऔर post_commentरिकॉर्ड के सभी संयोजन प्राप्त करेंगे :

| p.id    | pc.id      |
|---------|------------|
| 1       | 1          |
| 1       | 2          |
| 1       | 3          |
| 2       | 1          |
| 2       | 2          |
| 2       | 3          |
| 3       | 1          |
| 3       | 2          |
| 3       | 3          |

इसलिए, यदि ऑन क्लॉज शर्त "हमेशा सत्य" है, तो INNER JOIN केवल CROSS JOIN क्वेरी के बराबर है:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id

SQL INNER JOIN - "हमेशा झूठी" स्थिति पर

दूसरी ओर, यदि ON क्लॉज की स्थिति "हमेशा झूठी" है, तो सभी सम्मिलित किए गए रिकॉर्डों को फ़िल्टर किया जाएगा और परिणाम सेट खाली होगा।

इसलिए, यदि हम निम्नलिखित SQL INNER JOIN क्वेरी को निष्पादित करते हैं:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id

हमें कोई परिणाम वापस नहीं मिलेगा:

| p.id    | pc.id      |
|---------|------------|

ऐसा इसलिए है क्योंकि उपरोक्त क्वेरी निम्न क्रोस जॉइन क्वेरी के बराबर है:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id

SQL INNER JOIN - फॉरेन की और प्राइमरी की कॉलम का उपयोग करके क्लॉज

क्लॉज की सबसे सामान्य स्थिति वह है जो चाइल्ड टेबल में पैरेंट टेबल में प्राइमरी की के कॉलम के साथ चाइल्ड टेबल में फॉरेन की के कॉलम से मेल खाती है, जैसा कि निम्नलिखित क्वेरी द्वारा दर्शाया गया है:

SELECT
   p.id AS "p.id",
   pc.post_id AS "pc.post_id",
   pc.id AS "pc.id",
   p.title AS "p.title",
   pc.review  AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id

उपरोक्त SQL ININ JOIN क्वेरी को निष्पादित करते समय, हमें निम्न परिणाम सेट मिलते हैं:

| p.id    | pc.post_id | pc.id      | p.title    | pc.review |
|---------|------------|------------|------------|-----------|
| 1       | 1          | 1          | Java       | Good      |
| 1       | 1          | 2          | Java       | Excellent |
| 2       | 2          | 3          | Hibernate  | Awesome   |

इसलिए, ON रिकॉर्ड जो क्लॉज कंडीशन से मेल खाते हैं, उन्हें क्वेरी रिजल्ट सेट में शामिल किया गया है। हमारे मामले में, परिणाम सेट में postउनके post_commentरिकॉर्ड के साथ सभी शामिल हैं । जिन postपंक्तियों में कोई संबद्धता post_commentनहीं है उन्हें बाहर रखा गया है क्योंकि वे ऑन क्लॉज स्थिति को संतुष्ट नहीं कर सकते हैं।

पुन: उपरोक्त SQL INNER JOIN क्वेरी निम्न CROSS JOIN क्वेरी के बराबर है:

SELECT
   p.id AS "p.id",
   pc.post_id AS "pc.post_id",
   pc.id AS "pc.id",
   p.title AS "p.title",
   pc.review  AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id

गैर-पंक्तियाँ पंक्तियाँ हैं जो WHERE क्लॉज़ को संतुष्ट करती हैं, और केवल ये रिकॉर्ड परिणाम सेट में शामिल होने जा रहे हैं। यह कल्पना करने का सबसे अच्छा तरीका है कि INNER JOIN क्लॉज कैसे काम करता है।

| p.id | pc.post_id | pc.id | p.title | pc.review |
| ------ | ------------ | ------- | ----------- | --------- - |
| 1 | 1 | 1 | जावा | अच्छा है |
| 1 | 1 | 2 | जावा | उत्कृष्ट |
| 1 | 2 | 3 | जावा | बहुत बढ़िया | 
| 2 | 1 | 1 | हाइबरनेट | अच्छा है | 
| 2 | 1 | 2 | हाइबरनेट | उत्कृष्ट |
| 2 | 2 | 3 | हाइबरनेट | बहुत बढ़िया |
| 3 | 1 | 1 | जेपीए | अच्छा है | 
| 3 | 1 | 2 | जेपीए | उत्कृष्ट | 
| 3 | 2 | 3 | जेपीए | बहुत बढ़िया |

निष्कर्ष

एक INNER JOIN स्टेटमेंट को CROSS JOIN के रूप में फिर से लिखा जा सकता है, जिसमें INER JOIN क्वेरी के ON क्लाज में आपके द्वारा उपयोग की गई उसी स्थिति से मेल खाता है।

ऐसा नहीं है कि यह केवल INNER JOIN पर लागू होता है, OUTER JOIN के लिए नहीं।


11

जहां क्लॉज बनाम क्लॉज , जहां लेफ्ट जॉइन की बात आती है, वहां काफी अंतर है ।

यहाँ उदाहरण है:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

वहाँ fid तालिका t2 की आईडी है।

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

"खंड पर" पर प्रश्न:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

"जहाँ खंड" पर प्रश्न:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

यह स्पष्ट है कि, पहली क्वेरी t1 से एक रिकॉर्ड देती है और इसकी निर्भर पंक्ति t2 से, यदि कोई हो, पंक्ति t1.v = 'K' के लिए।

दूसरी क्वेरी t1 से पंक्तियों को लौटाती है, लेकिन केवल t1.v = 'K' के लिए इसके साथ कोई संबद्ध पंक्ति होगी।


9

ऑप्टिमाइज़र के संदर्भ में, इससे कोई फ़र्क नहीं पड़ना चाहिए कि क्या आप अपने जॉइन क्लॉज़ को ON या WHERE से परिभाषित करते हैं।

हालांकि, IMHO, मुझे लगता है कि जब प्रदर्शन करते हैं तो ON क्लॉज का उपयोग करना अधिक स्पष्ट होता है। इस तरह से आपके पास एक विशिष्ट खंड होता है, जिसमें यह लिखा होता है कि बाकी संधि के साथ जुड़ने का तरीका कैसे नियंत्रित किया जाता है।


7

आइए उन तालिकाओं पर विचार करें:

id | SomeData

बी

id | id_A | SomeOtherData

id_A तालिका के लिए एक विदेशी कुंजी होने के नाते A

इस प्रश्न को लिखते हुए:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;

यह परिणाम प्रदान करेगा:

/ : part of the result
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+-------+-------------------------+
|/////////////////////////////|
+-----------------------------+

A में क्या है, लेकिन B में नहीं है, इसका मतलब है कि B के लिए शून्य मान है।


अब, आइए एक विशिष्ट भाग पर विचार करें B.id_Aऔर इसे पिछले परिणाम से उजागर करें:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+---+///|                         |
|/////////////////////|***|///|                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

इस प्रश्न को लिखते हुए:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
AND B.id_A = SpecificPart;

यह परिणाम प्रदान करेगा:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|       |                         |
|/////////////////////|       |                         |
|/////////////////////+---+   |                         |
|/////////////////////|***|   |                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

क्योंकि यह आंतरिक में उन मूल्यों से जुड़ जाता है जो अंदर नहीं हैं B.id_A = SpecificPart


अब, इस से क्वेरी को बदलते हैं:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
WHERE B.id_A = SpecificPart;

परिणाम अब है:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|                     |       |                         |
|                     |       |                         |
|                     +---+   |                         |
|                     |***|   |                         |
|                     +---+---+-------------------------+
|                             |
+-----------------------------+

क्योंकि पूरा परिणाम B.id_A = SpecificPartभागों को हटाने के खिलाफ फ़िल्टर किया गया है B.id_A = NULL, जो कि बी में नहीं हैं


4

क्या आप डेटा या फ़िल्टर डेटा से जुड़ने का प्रयास कर रहे हैं?

पठनीयता के लिए यह इन उपयोग मामलों को क्रमशः और WHERE पर अलग करने के लिए सबसे अधिक समझ में आता है।

  • ON में डेटा मिलाएं
  • WHERE में डेटा फ़िल्टर करें

जहाँ क्वेरी स्थिति और फ़िल्टरिंग स्थिति WHERE क्लॉज में मौजूद है, वहां क्वेरी पढ़ना बहुत मुश्किल हो सकता है।

प्रदर्शन के हिसाब से आपको कोई अंतर नहीं देखना चाहिए, हालाँकि SQL के विभिन्न प्रकार कभी-कभी क्वेरी प्लानिंग को अलग तरीके से हैंडल करते हैं, इसलिए यह कोशिश करने लायक हो सकता है ¯\_(ツ)_/¯(क्वेरी गति को प्रभावित करने वाले कैशिंग के बारे में जागरूक रहें)

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

मैंने इस बारे में गहराई से एक और पोस्ट यहाँ लिखी है: https://dataschool.com/learn/difference-between-where-and-on-in-sql


2

SQL में, 'WHERE' और 'ON' क्लॉज, तरह-तरह के Conditional Statemants हैं, लेकिन उनके बीच प्रमुख अंतर यह है कि, '' कहां '' क्लॉज का उपयोग शर्तों को निर्दिष्ट करने के लिए Select / Update स्टेटमेंट में किया जाता है, जबकि 'ON' क्लॉज Joins में उपयोग किया जाता है, जहाँ यह सत्यापित करता है या जाँचता है कि अभिलेख लक्ष्य और स्रोत तालिकाओं में मेल खाते हैं, इससे पहले कि Tables ज्वाइन किया जाता है

उदाहरण के लिए: - 'WHERE'

SELECT * FROM employee WHERE employee_id=101

उदाहरण के लिए: - 'चालू'

दो टेबल कर्मचारी और कर्मचारी_डेट हैं, मेल खाने वाले कर्मचारी कर्मचारी हैं।

SELECT * FROM employee 
INNER JOIN employee_details 
ON employee.employee_id = employee_details.employee_id

आशा है कि मैंने आपके प्रश्न का उत्तर दे दिया है। किसी भी स्पष्टीकरण के लिए वापस।


लेकिन आप के WHEREस्थान पर कीवर्ड का उपयोग कर सकते हैं ON, क्या आप नहीं कर सकते? sqlfiddle.com/# -2
क्वर्टी

1

मुझे लगता है कि यह जुड़ाव अनुक्रम प्रभाव है। ऊपरी बाएँ ज्वाइन केस में, SQL do Left join पहले होता है और फिर फ़िल्टर कहाँ होता है। नीचे के मामले में, पहले Orders.ID = 12345 खोजें, और फिर शामिल हों।


1

एक आंतरिक जुड़ाव के लिए, WHEREऔर ONइसे परस्पर उपयोग किया जा सकता है। वास्तव में, यह ONसहसंबंधित उप-वर्ग में उपयोग करना संभव है । उदाहरण के लिए:

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

यह (IMHO) पूरी तरह से मानव को भ्रमित करने वाला है, और table1किसी भी चीज़ से लिंक करना भूल जाना बहुत आसान है (क्योंकि "ड्राइवर" तालिका में "खंड" पर "" नहीं है, लेकिन यह कानूनी है।


1

बेहतर प्रदर्शन तालिकाओं के लिए JOINS का उपयोग करने के लिए एक विशेष अनुक्रमित स्तंभ होना चाहिए।

इसलिए यदि आप जिस कॉलम पर शर्त लगाते हैं, वह उन अनुक्रमित स्तंभों में से एक नहीं है, तो मुझे संदेह है कि इसे WHERE में रखना बेहतर है।

इसलिए आप अनुक्रमित स्तंभों का उपयोग करके शामिल हों, फिर जोइन करने के बाद आप किसी भी अनुक्रमित स्तंभ पर स्थिति नहीं चलाते हैं।


1

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


यह केवल इसलिए नहीं है क्योंकि DBMSs "सामान्य रूप से" अनुकूलन करते हैं।
फिलिप्पिक्स

1

मुझे लगता है कि इस अंतर को SQL में परिचालन के तार्किक क्रम के माध्यम से सबसे अच्छा समझाया जा सकता है , जो कि सरलीकृत है:

  • FROM (जॉइन सहित)
  • WHERE
  • GROUP BY
  • एकत्रीकरण
  • HAVING
  • WINDOW
  • SELECT
  • DISTINCT
  • UNION, INTERSECT,EXCEPT
  • ORDER BY
  • OFFSET
  • FETCH

जॉइन सिलेक्ट स्टेटमेंट का क्लॉज नहीं है, लेकिन इसके अंदर एक ऑपरेटर है FROM। जैसे, ONसंगत JOINऑपरेटर से संबंधित सभी क्लॉज तार्किक प्रसंस्करण द्वारा क्लॉज तक पहुंचने तक तार्किक रूप से "पहले ही हो चुके हैं" WHERE। इसका मतलब यह है कि LEFT JOINउदाहरण के लिए, बाहरी जुड़ाव के शब्दार्थ पहले ही समय के हिसाब से खुश हो चुके हैंWHERE क्लॉज लागू ।

मैंने इस ब्लॉग पोस्ट में निम्नलिखित उदाहरण को अधिक गहराई से समझाया है । इस क्वेरी को चलाते समय:

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

LEFT JOINवास्तव में, क्योंकि भले ही एक अभिनेता एक फिल्म में नहीं खेला था, अभिनेता फ़िल्टर कर दिया जाएगा, किसी भी उपयोगी प्रभाव नहीं पड़ता है के रूप में अपनी FILM_IDहो जाएगा NULLऔर WHEREखंड में इस तरह के एक पंक्ति फिल्टर करेगा। परिणाम कुछ इस प्रकार है:

ACTOR_ID  FIRST_NAME  LAST_NAME  COUNT
--------------------------------------
194       MERYL       ALLEN      1
198       MARY        KEITEL     1
30        SANDRA      PECK       1
85        MINNIE      ZELLWEGER  1
123       JULIANNE    DENCH      1

Ie के रूप में अगर हम आंतरिक रूप से दो तालिकाओं में शामिल हो गए। यदि हम फ़िल्टर को ONक्लॉज़ में विधेय की ओर ले जाते हैं , तो यह अब बाहरी जुड़ने का एक मापदंड बन जाता है:

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
  AND film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

मतलब परिणाम में किसी भी फिल्म के बिना या बिना किसी फिल्म के अभिनेता शामिल होंगे FILM_ID < 10

ACTOR_ID  FIRST_NAME  LAST_NAME     COUNT
-----------------------------------------
3         ED          CHASE         0
4         JENNIFER    DAVIS         0
5         JOHNNY      LOLLOBRIGIDA  0
6         BETTE       NICHOLSON     0
...
1         PENELOPE    GUINESS       1
200       THORA       TEMPLE        1
2         NICK        WAHLBERG      1
198       MARY        KEITEL        1

संक्षेप में

हमेशा अपने विधेय को रखें जहां यह तार्किक रूप से सबसे अधिक समझ में आता है।


0

आपके प्रश्न के बारे में,

जब तक आपका सर्वर इसे प्राप्त कर सकता है, तब तक यह 'ऑन' या 'जहां' दोनों में समान है।

select * from a inner join b on a.c = b.c

तथा

select * from a inner join b where a.c = b.c

'जहाँ' विकल्प सभी दुभाषियों को नहीं पता है इसलिए शायद इससे बचा जाना चाहिए। और निश्चित रूप से 'ऑन' क्लॉज स्पष्ट है।


-5

यह मेरा समाधान है।

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

आपको इसे काम करने के लिए प्राप्त करना होगाGROUP BY

उममीद है कि इससे मदद मिलेगी।


10
केवल गानों.फ्लिनेम पर ग्रुप बनाना जबकि आप भी गाने_ड और सिंगर्स का चयन कर रहे हैं। पिफनाम ज्यादातर डेटाबेस में एक समस्या होने वाली है।
btilly
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.