PostgreSQL: आउटर जॉइन में ON बनाम WHERE - कब शर्त का स्थानांतरण परिणाम बदल देता है
आउटर जॉइन में ON में दी गई शर्त जॉइन के दौरान लागू होती है, जबकि WHERE पहले से बने परिणाम को फ़िल्टर करता है, इसलिए फ़िल्टर को एक जगह से दूसरी जगह ले जाने से यह बदल सकता है कि कौन-सी पंक्तियाँ बचेंगी। इनर जॉइन के लिए स्थान केवल शैलीगत मामला है।
इस पृष्ठ पर
मुख्य विचार
PostgreSQL में, जॉइन के ON क्लॉज़ में दी गई शर्त जॉइन की गई टेबल बनाने के हिस्से के रूप में मूल्यांकित होती है, जबकि WHERE में दी गई शर्त FROM क्लॉज़ के तैयार परिणाम पर लागू होती है। आउटर जॉइन के लिए इससे परिणाम बदल जाता है: ON तय करती है कि कौन-सी पंक्तियाँ मैच करती हैं और इसलिए कौन-सी null-extended पंक्तियाँ जोड़ी जाएँगी, जबकि WHERE केवल जॉइन से बनी पंक्तियों को हटा सकता है। यदि आप दूसरी ओर की बिना मैच वाली पंक्तियों को सुरक्षित रखना चाहते हैं तो आउटर जॉइन की nullable ओर को प्रतिबंधित करने वाली शर्तें ON में रखें; अंतिम परिणाम फ़िल्टर करने वाली शर्तें WHERE में रखें। इनर जॉइन के लिए दोनों स्थान समतुल्य हैं और चुनाव केवल शैलीगत है।
संदर्भ: PostgreSQL आउटर जॉइन में ON और WHERE को कैसे प्रोसेस करता है
PostgreSQL किसी क्वेरी की टेबल एक्सप्रेशन को एक पाइपलाइन की तरह बनाता है: FROM क्लॉज़ एक मध्यवर्ती वर्चुअल टेबल बनाता है, और फिर WHERE, GROUP BY तथा HAVING उसे रूपांतरित करते हैं। FROM के भीतर, एक qualified join की शर्त ON (या USING) क्लॉज़ में रहती है, और यह तय करती है कि दोनों स्रोतों की कौन-सी पंक्तियाँ मैच मानी जाएँगी। LEFT OUTER JOIN के लिए PostgreSQL पहले एक इनर जॉइन करता है, फिर हर उस बाईं ओर की पंक्ति के लिए एक पंक्ति जोड़ता है जिसका कोई मैच नहीं मिला, और दाईं ओर के कॉलम null से भर देता है। इसका अर्थ है कि ON क्लॉज़ दो काम करती है: वह गैर-मैचिंग संयोजनों को हटाती है और बिना मैच वाली बाईं पंक्तियों के लिए null-extended पंक्तियाँ जोड़ती है।
WHERE की ऐसी कोई भूमिका नहीं है। यह FROM क्लॉज़ द्वारा जॉइन की गई टेबल बनने के बाद चलता है और केवल उन पंक्तियों को हटा देता है जो उसकी खोज शर्त को पूरा नहीं करतीं। दस्तावेज़ीकरण यह क्रम स्पष्ट रूप से बताता है: ON क्लॉज़ में दी गई प्रतिबंध शर्त जॉइन से पहले प्रोसेस होती है, जबकि WHERE क्लॉज़ में दी गई शर्त जॉइन के बाद प्रोसेस होती है। इनर जॉइन के लिए यह क्रम परिणाम में दिखाई नहीं देता, लेकिन आउटर जॉइन के लिए दिखता है, क्योंकि दाईं ओर के कॉलम पर WHERE की शर्त उन्हीं null-extended पंक्तियों को रद्द कर सकती है जिन्हें आउटर जॉइन को सुरक्षित रखना था।
SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num WHERE t2.value = 'xxx';; num | name | num | value;-----+------+-----+-------; 1 | a | 1 | xxx;(1 row)सिफ़ारिश: शर्तें कहाँ रखें, और समझौते क्या हैं
एक व्यावहारिक नियम: यदि कोई शर्त आउटर जॉइन के nullable (दाईं) ओर को प्रतिबंधित करती है और आप सुरक्षित (बाईं) ओर की बिना मैच वाली पंक्तियाँ फिर भी रखना चाहते हैं, तो उसे ON में रखें। यदि शर्त का उद्देश्य अंतिम परिणाम को फ़िल्टर करना है, जिसमें null-extended पंक्तियों को हटाना भी शामिल है, तो उसे WHERE में रखें। LEFT JOIN की सुरक्षित (बाईं) ओर पर दी गई शर्तें दोनों जगहों पर इस अर्थ में समान व्यवहार करती हैं कि कौन-सी बाईं पंक्तियाँ बचेंगी, लेकिन उन्हें ON में रखने से जॉइन आत्मनिहित रहता है और बाद में जॉइन का प्रकार बदलने पर अप्रत्याशित परिणामों से बचा जाता है। इनर जॉइन के लिए दस्तावेज़ीकरण बताता है कि जॉइन शर्त WHERE या JOIN क्लॉज़ में लिखी जा सकती है और चुनाव मुख्यतः शैली का विषय है; पठनीयता और टीम की परंपराओं को निर्णय लेने देना चाहिए। ध्यान दें कि आउटर जॉइन स्वयं FROM क्लॉज़ में ही लिखे जाने चाहिए; उनके लिए केवल-WHERE वाला कोई रूप नहीं है।
इसमें समझौता अर्थगत स्पष्टता बनाम संक्षिप्तता का है। गैर-जॉइन शर्तों को ON में मिलाने से क्वेरी पढ़ने में कठिन हो सकती है, लेकिन ऐसी शर्त को WHERE में हटाने से 'बिना मैच वाली पंक्तियाँ रखने' वाली क्वेरी चुपचाप इनर-जॉइन जैसे परिणाम में बदल जाती है। समीक्षा या रिफैक्टरिंग के समय आउटर जॉइन की ON/WHERE सीमा के पार किसी भी शर्त को स्थानांतरित करने को एक अर्थगत परिवर्तन मानें, केवल कॉस्मेटिक परिवर्तन नहीं।
SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num AND t2.value = 'xxx';; num | name | num | value;-----+------+-----+-------; 1 | a | 1 | xxx; 2 | b | |; 3 | c | |;(3 rows)ठोस उदाहरण: t2.value पर शर्त के साथ LEFT JOIN
दस्तावेज़ीकरण के उदाहरण में दो तालिकाएँ हैं, जहाँ t1 में पंक्तियाँ (1,a), (2,b), (3,c) हैं और t2 में (1,xxx) तथा (3,yyy) हैं। जब शर्त ON के अंदर होती है, तो जॉइन केवल उसी t2 पंक्ति से मेल खाता है जिसका मान 'xxx' है; t1 की पंक्तियाँ 2 और 3 को कोई योग्य मेल नहीं मिलता, इसलिए वे t2 के कॉलम में NULL के साथ लौटाई जाती हैं, जिससे तीन पंक्तियाँ मिलती हैं। वही शर्त जब WHERE में होती है, तो जॉइन पहले केवल num के आधार पर मेल खाता है, जिससे जोड़ियों (1,xxx) और (3,yyy) के लिए पंक्तियाँ बनती हैं, और फिर WHERE हर उस पंक्ति को हटा देता है जहाँ t2.value 'xxx' नहीं है - और यह null-विस्तारित पंक्तियों को भी हटा देता है, क्योंकि NULL = 'xxx' सत्य नहीं है। केवल एक पंक्ति बचती है। नीचे दिए गए उदाहरण आउटपुट दस्तावेज़ीकरण के उदाहरण के अनुसार हैं; पुष्टि करने के लिए इन्हें अपने स्वयं के सीड डेटा पर चलाएँ।
SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num AND t2.value = 'xxx'; -- returns 3 rows: (1,a,1,xxx), (2,b,NULL,NULL), (3,c,NULL,NULL) SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num WHERE t2.value = 'xxx'; -- returns 1 row: (1,a,1,xxx)लागू होने की सीमाएँ
यह अंतर केवल LEFT, RIGHT और FULL आउटर जॉइन के लिए मायने रखता है, क्योंकि केवल इनके ON क्लॉज़ ही पंक्तियों को हटाते भी हैं और जोड़ते भी हैं। INNER JOIN के लिए ON और WHERE समतुल्य हैं और स्थान केवल शैली का विषय है। यहाँ दी गई सलाह केवल परिणाम के अर्थशास्त्र से संबंधित है; यह इस बारे में कुछ नहीं कहती कि प्लानर कौन सा प्लान या इंडेक्स चुनेगा, और प्रदर्शन संबंधी प्रश्नों के लिए अभी भी वास्तविक प्लान को मापना आवश्यक है। उदाहरण PostgreSQL 18 के दस्तावेज़ीकरण को दर्शाते हैं; JOIN सिंटैक्स मानक SQL है, लेकिन अन्य डेटाबेस सिस्टम में व्यवहार पर भरोसा करने से पहले उसे सत्यापित करें। यह भी याद रखें कि FROM सूची में JOIN, कॉमा से अधिक कसकर बंधता है, इसलिए कॉमा और JOIN की मिश्रित सूचियाँ बदल सकती हैं कि कोई ON शर्त किन तालिकाओं को संदर्भित कर सकती है।
FROM T1 CROSS JOIN T2 INNER JOIN T3 ON condition -- the condition can reference T1 here,;-- but not in the comma-list equivalent;FROM T1, T2 INNER JOIN T3 ON conditionउपयोग की शर्तें
- क्या शर्त आउटर जॉइन की nullable ओर के कॉलम को संदर्भित करती है? यदि हाँ, तो ON बनाम WHERE का स्थान परिणाम बदल देगा।
- क्या आप चाहते हैं कि सुरक्षित ओर की बिना मैच वाली पंक्तियाँ NULL के साथ दिखें? तब प्रतिबंध ON में होना चाहिए।
- क्या जॉइन एक INNER JOIN है? तब स्थान केवल शैली का विकल्प है, शुद्धता का मुद्दा नहीं।
- क्या आउटर जॉइन FROM क्लॉज़ में लिखा गया है? इसे केवल-WHERE शर्त के रूप में व्यक्त नहीं किया जा सकता।
- क्या FROM सूची में कॉमा और JOIN मिले हुए हैं? याद रखें कि JOIN कॉमा से अधिक तंग बंधता रखता है, जो ON के संदर्भों को प्रभावित करता है।
उपयोग की सीमाएँ
यह PostgreSQL 18 के दस्तावेज़ीकरण के अनुसार ON और WHERE के बीच शर्तें हटाने के परिणामी अर्थशास्त्र को कवर करता है; यह प्लानर व्यवहार, प्रदर्शन या गैर-मानक SQL डायलेक्टों को संबोधित नहीं करता।