INNER JOIN और LEFT JOIN में अंतर: SQL उदाहरण और आम गलतियाँ
सिर्फ मेल खाती पंक्तियाँ चाहिए तो INNER JOIN चुनें। बाईं टेबल की हर पंक्ति रखनी हो, भले ही दाईं टेबल में मेल न मिले, तो LEFT JOIN चुनें। ग्राहक रिपोर्ट, अधूरे डेटा की जाँच और इंटरव्यू में यह अंतर काम आता है।
मान लें कि ग्राहकों के साथ उनके ऑर्डर दिखाने हैं। दो ऑर्डर वाला ग्राहक दो बार आएगा: JOIN मेल खाती जोड़ियाँ लौटाता है, हर ग्राहक के लिए अपने आप एक पंक्ति नहीं। बिना ऑर्डर वाला ग्राहक INNER JOIN से हट जाता है, लेकिन LEFT JOIN में उसके ऑर्डर कॉलम NULL होते हैं।
| रिपोर्ट का सवाल | सही JOIN |
|---|---|
| किन ग्राहकों के ऑर्डर हैं? | INNER JOIN |
| सभी ग्राहक दिखाएँ, बिना ऑर्डर वाले भी | LEFT JOIN |
| बिना ऑर्डर वाले ग्राहक खोजें | LEFT JOIN और NULL की जाँच |
नीचे दिए उदाहरण में नतीजों से यह अंतर साफ दिखता है।
SQLite में खुद चलाकर देखें
SQL Lab खोलें, यह सेटअप पेस्ट करें और एक बार चलाएँ। फिर हर क्वेरी अलग चलाएँ। टेबल और कॉलम के नाम अंग्रेज़ी में रखे गए हैं ताकि हर भाषा में वही SQL चले। लैब और लिंक किए गए पाठ के निर्देश अभी अंग्रेज़ी में हैं।
CREATE TABLE blog_customers (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE blog_orders (
id INTEGER PRIMARY KEY, customer_id INTEGER, status TEXT, amount INTEGER
);
INSERT INTO blog_customers VALUES (1, 'Asha'), (2, 'Luis'), (3, 'Mei');
INSERT INTO blog_orders VALUES
(101, 1, 'paid', 120), (102, 1, 'pending', 80), (103, 2, 'paid', 60);
1. INNER JOIN सिर्फ मेल खाती पंक्तियाँ लौटाता है
Asha के दो ऑर्डर हैं, Luis का एक और Mei का कोई नहीं। INNER JOIN तीन पंक्तियाँ देता है। Mei नहीं दिखती क्योंकि कोई ऑर्डर JOIN की शर्त पूरी नहीं करता।
SELECT c.name, o.id AS order_id, o.status
FROM blog_customers AS c
INNER JOIN blog_orders AS o ON o.customer_id = c.id
ORDER BY c.id, o.id;
अपेक्षित नतीजा
| name | order_id | status |
|---|---|---|
| Asha | 101 | paid |
| Asha | 102 | pending |
| Luis | 103 | paid |
2. LEFT JOIN सभी ग्राहकों को रखता है
अब Mei भी दिखती है। मेल खाता ऑर्डर न होने पर दाईं टेबल के कॉलम NULL होते हैं। Asha अभी भी दो बार आती है; सभी ग्राहकों को रखने का मतलब एक ग्राहक के कई ऑर्डर हटाना नहीं है।
SELECT c.name, o.id AS order_id, o.status
FROM blog_customers AS c
LEFT JOIN blog_orders AS o ON o.customer_id = c.id
ORDER BY c.id, o.id;
अपेक्षित नतीजा
| name | order_id | status |
|---|---|---|
| Asha | 101 | paid |
| Asha | 102 | pending |
| Luis | 103 | paid |
| Mei | NULL | NULL |
NULL का मतलब है कि कोई मेल खाती वैल्यू नहीं है; यह शून्य या खाली स्ट्रिंग नहीं है।
3. ग्राहकों को बचाए रखने के लिए ON में फ़िल्टर लगाएँ
हर ग्राहक के साथ केवल paid ऑर्डर दिखाने हों तो status की शर्त ON में रखें। केवल pending ऑर्डर वाला ग्राहक भी रहेगा, लेकिन ऑर्डर कॉलम NULL होंगे। यह शर्त तय करती है कि कौन सा ऑर्डर मेल खा सकता है।
SELECT c.name, o.id AS order_id
FROM blog_customers AS c
LEFT JOIN blog_orders AS o
ON o.customer_id = c.id AND o.status = 'paid'
ORDER BY c.id, o.id;
अपेक्षित नतीजा
| name | order_id |
|---|---|
| Asha | 101 |
| Luis | 103 |
| Mei | NULL |
4. WHERE ज़रूरी पंक्तियाँ हटा सकता है
वही शर्त WHERE में रखने पर सवाल बदल जाता है। WHERE जुड़ चुकी पंक्तियों को फ़िल्टर करता है। Mei का NULL status, status = 'paid' को पूरा नहीं करता, इसलिए Mei हट जाती है। इसी गलती से LEFT JOIN का नतीजा कई बार INNER JOIN जैसा दिखता है।
SELECT c.name, o.id AS order_id
FROM blog_customers AS c
LEFT JOIN blog_orders AS o ON o.customer_id = c.id
WHERE o.status = 'paid'
ORDER BY c.id, o.id;
अपेक्षित नतीजा
| name | order_id |
|---|---|
| Asha | 101 |
| Luis | 103 |
5. असली ऑर्डर गिनें, बची हुई ग्राहक पंक्ति नहीं
COUNT(o.id) Mei के NULL ऑर्डर ID को नहीं गिनता, इसलिए सही उत्तर शून्य है। COUNT(*) उस ग्राहक की बची हुई पंक्ति गिनेगा और एक बताएगा। यहाँ ऑर्डर ID non-null primary key है, इसलिए उसे गिनना सही है।
SELECT c.name, COUNT(o.id) AS order_count
FROM blog_customers AS c
LEFT JOIN blog_orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;
अपेक्षित नतीजा
| name | order_count |
|---|---|
| Asha | 2 |
| Luis | 1 |
| Mei | 0 |
अभ्यास और उत्तर की जाँच
ऐसे ग्राहक खोजें जिनके कोई paid ऑर्डर नहीं हैं, चाहे pending ऑर्डर हों। ऊपर वाले paid-order LEFT JOIN में ORDER BY से पहले WHERE o.id IS NULL जोड़ें। इस डेटा में उत्तर Mei है।
NULL की जाँच के लिए दाईं टेबल की non-null key चुनें। delivery note जैसे nullable कॉलम की जाँच से असली ऑर्डर भी गायब ऑर्डर समझा जा सकता है। JOIN का संबंध समझे बिना DISTINCT लगाकर दोहराव न छिपाएँ; गलती JOIN की शर्त में हो सकती है।
प्रति ग्राहक एक पंक्ति चाहिए तो JOIN के बाद GROUP BY से सारांश बनाएँ, जैसे गिनती वाले उदाहरण में। ऑर्डर-स्तर की रिपोर्ट के लिए अलग ऑर्डर पंक्तियाँ रखें। पहले तय करें कि रिपोर्ट की एक पंक्ति किस चीज़ को दर्शाएगी।
दस्तावेज़ और आगे की पढ़ाई
INNER JOIN का पाठ और LEFT/RIGHT JOIN का पाठ पढ़ें। उदाहरण SQLite पर चलते हैं और यही syntax PostgreSQL तथा MySQL में भी उपलब्ध है। दूसरे JOIN प्रकार और क्वेरी का execution plan डेटाबेस पर निर्भर करते हैं।
SQL Lab में उदाहरण चलाएँ
इस गाइड का सेटअप और क्वेरी लैब में कॉपी करें। उदाहरण SQLite पर चलते हैं। पाठ और लैब के निर्देश अभी अंग्रेज़ी में हैं।
SQL Lab खोलें