TATECHATLAS
◎ हिन्दी
डेटा और डेटाबेस

SQL में NULL की तुलना शून्य जैसी क्यों नहीं होती

IS NULL, तीन-मान वाली लॉजिक और COUNT(*) तथा COUNT(column) के अंतर को समझें।

इस पृष्ठ पर

NULL का अर्थ है कि मान उपलब्ध नहीं है या अज्ञात है। = या <> से किसी मान की NULL से तुलना करने पर परिणाम अज्ञात होता है। WHERE केवल सही शर्तों वाली पंक्तियाँ रखता है, इसलिए अनुपलब्ध मान खोजने के लिए IS NULL इस्तेमाल करें।

तीन पंक्तियों से अंतर समझें

तीन खातों के बैलेंस 100, 0 और NULL मानें। खाते तीन हैं, लेकिन ज्ञात बैलेंस केवल दो हैं। तीसरे खाते में शून्य, ऋण या धनात्मक रकम हो सकती है; डेटा इसका उत्तर नहीं देता। इसलिए बैलेंस की जानकारी न होना, पैसे न होने का प्रमाण नहीं है।

नीचे की क्वेरी VALUES से डेटा बनाती है, इसलिए पहले से कोई टेबल नहीं चाहिए। परिणाम total_rows = 3, known_balances = 2 और mean_known = 50 होगा। NULL को शून्य बनाने पर mean_with_zero लगभग 33.33 हो जाता है। औसत का हर बदल गया है: यह रिपोर्ट के अर्थ में बदलाव है, केवल खाली सेल का स्वरूप बदलना नहीं।

WITH balances(balance) AS (
  VALUES (100::numeric), (0::numeric), (NULL::numeric)
)
SELECT COUNT(*) AS total_rows,
       COUNT(balance) AS known_balances,
       AVG(balance) AS mean_known,
       AVG(COALESCE(balance, 0)) AS mean_with_zero
FROM balances;

अनुपलब्ध मान ढूँढें

अनुपलब्ध बैलेंस का अर्थ अपने-आप शून्य बैलेंस नहीं होता। यह अंतर स्पष्ट रखें। दो अनुपलब्ध मानों को बराबर मानने वाली तुलना के लिए PostgreSQL में IS NOT DISTINCT FROM उपलब्ध है।

SELECT * FROM accounts WHERE balance IS NULL;
SELECT a IS NOT DISTINCT FROM b;

पंक्तियाँ सोच-समझकर गिनें

COUNT(*) पंक्तियाँ गिनता है। COUNT(balance) केवल उन बैलेंस मानों को गिनता है जो NULL नहीं हैं। COALESCE(balance, 0) अनुपलब्ध बैलेंस की जगह शून्य रखता है; ऐसा तभी करें जब यह बदलाव आपके डेटा के अर्थ के अनुरूप हो।

फ़िल्टर कुछ पंक्तियाँ क्यों हटाता है

इन्हीं मानों पर WHERE balance <> 0 केवल 100 रखता है। शून्य के लिए शर्त false और NULL के लिए unknown है। यदि गैर-शून्य तथा अज्ञात दोनों बैलेंस चाहिए, तो balance <> 0 OR balance IS NULL लिखें।

शर्त को उलटना मदद नहीं करता: NULL के लिए NOT(balance = 0) भी unknown है। पहले तय करें कि अज्ञात मानों का व्यवहार क्या होना चाहिए, फिर SQL लिखें। रिपोर्ट का कुल गलत लगे तो चुनी गई पंक्तियों के साथ हटाई गई पंक्तियाँ भी देखें।

NOT IN में NULL की समस्या

मानें कि पहचान संख्या 2 हटानी है, लेकिन सूची में NULL भी आ गया। 1 NOT IN (2, NULL) भी unknown होगा: SQL यह साबित नहीं कर सकता कि 1 सूची के हर मान से अलग है। WHERE में ऐसी शर्त पंक्ति को हटा देती है।

बहिष्करण वाली सबक्वेरी के लिए स्पष्ट मिलान शर्त के साथ NOT EXISTS पर विचार करें। यह किसी मिलती पंक्ति के न होने की जाँच करता है और सूची का NULL सीधे नहीं अपनाता। फिर भी, पहचान संख्या स्वयं अज्ञात होने पर क्या करना है, यह अलग से तय करें; केवल सिंटैक्स बदलने से व्यावसायिक नियम नहीं बनता।

SELECT 1 NOT IN (2, NULL) AS result;

LEFT JOIN के बाद अज्ञात मान

LEFT JOIN बाईं टेबल की पंक्तियाँ रखता है और मिलान न मिलने पर दाईं ओर NULL भरता है। दाईं टेबल के फ़ील्ड पर WHERE में शर्त लगाने से ये बिना मिलान वाली पंक्तियाँ हट सकती हैं। सभी खाते रखने और दाईं तरफ केवल सक्रिय रिकॉर्ड जोड़ने हों, तो वह प्रतिबंध ON में रखें।

COALESCE लगाने से पहले कारण समझें: डेटा नहीं लिया गया, फ़ील्ड लागू नहीं है या JOIN में रिकॉर्ड नहीं मिला? इन स्थितियों को अलग नाम देने पड़ सकते हैं। पहले कुल पंक्तियाँ, ज्ञात मान और अज्ञात मान गिनें; JOIN देखें; उसके बाद रिपोर्ट के लिए उचित प्रतिस्थापन चुनें।

क्या जाँचें

  • = NULL के बजाय IS NULL इस्तेमाल करें।
  • तय करें कि अनुपलब्ध मान का अर्थ वास्तव में शून्य है या नहीं।
  • पंक्तियों की संख्या को NULL के अलावा उपलब्ध मानों की संख्या से मिलाएँ।

उदाहरण PostgreSQL के लिए हैं। NULL से जुड़े नियम और NULL की तुलना के विशेष ऑपरेटर दूसरे डेटाबेस में अलग हो सकते हैं।

स्रोत

  1. PostgreSQL: comparison operators ↗
  2. PostgreSQL: conditional expressions ↗
  3. PostgreSQL: aggregate functions ↗
  4. PostgreSQL: SELECT ↗
  5. PostgreSQL: subquery expressions ↗
  6. PostgreSQL: joins and table expressions ↗
ऊपर जाएँ ↑