NULL को पहले क्यों सॉर्ट किया जाता है?


20

ऐसा क्यों है कि जब हमारे पास एक कॉलम में NULL मान होता है और हम आरोही मान द्वारा आदेश देते हैं, तो NULL को पहले क्रमबद्ध किया जाता है?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

का परिणाम

NULL
1
2
3
4

मैं सोचता रहता हूं कि NULL का मतलब "Indeterminant" या संभव "अज्ञात" था। यदि यह सच है, तो क्या वे अंतिम रूप नहीं देंगे, क्योंकि मूल्य अन्य सभी मूल्यों से अधिक हो सकता है? (या यह कहीं एक छँटाई विकल्प है?)

मैं SQL Server 2008R2 पर हूं, लेकिन मुझे संदेह है कि यह सभी SQL सर्वर पर, और संभवतः सभी RDBMS के पार है।


1
ओरेकल इसे अंतिम रूप से सूचीबद्ध करता है। यह एक बार मुझे खराब कर दिया, यह विश्वास करते हुए कि यह SQL सर्वर की तरह व्यवहार करना चाहिए।
आंद्रेई रोनेया

2
"अगर यह सच है, तो क्या वे अंतिम रूप नहीं देंगे, क्योंकि मूल्य अन्य सभी मूल्यों से अधिक हो सकता है"। मूल्य अन्य सभी मूल्यों से भी कम हो सकता है। मेरे लिए, यह सहज है कि अशक्त की तरह एक गलत मूल्य निचले छोर पर होना चाहिए। और व्यावहारिक रूप से, व्यवहार में, आप अक्सर descसबसे बड़ी या सबसे हाल की चीजों को दिखाने के लिए आदेश का उपयोग करना चाहते हैं, जिस स्थिति में मैं अशक्त चीजों के लिए अंतिम रूप से प्रसन्न हूं।
Mahemoff

डेटाबेस वह करता है जो आप उसे करने के लिए कहते हैं। यदि आप जानते हैं कि आपके डेटा में नल हैं और आपके पास डेटा को एक निश्चित तरीके से सॉर्ट करने के लिए कुछ व्यावसायिक कारण हैं, तो आपको यह निर्दिष्ट करने की आवश्यकता है कि डेटा को संसाधित / प्रदर्शित करने वाले क्वेरी या कोड / दृश्य में से कोई एक है। डिफ़ॉल्ट डेटाबेस व्यवहार तक को छाँटना कभी न छोड़ें।
कुछ भी नहीं

जवाबों:


19

BOL : NULL का मान इंगित करता है कि मान अज्ञात है। रिक्त का मान रिक्त या शून्य मान से भिन्न होता है। कोई दो शून्य मान समान नहीं हैं। दो अशक्त मानों के बीच, या एक NULL और किसी भी अन्य मान के बीच तुलना, अज्ञात लौटें क्योंकि प्रत्येक NULL का मान अज्ञात है।

NULL का मतलब अज्ञात है। कोई अन्य व्याख्या मान्य नहीं है।

यदि यह सच है, तो क्या वे अंतिम रूप नहीं देंगे, क्योंकि मूल्य अन्य सभी मूल्यों से अधिक हो सकता है?

नहीं हो सकता है । कोई संभावित मूल्य नहीं है। अज्ञात है अज्ञात।

जैसा कि यह प्रतीत होता है कि अंतिम के बजाय, यह प्रकाशित SQL मानकों द्वारा पूरा नहीं किया गया है और दुर्भाग्य से RDBMS विक्रेता के विवेक पर छोड़ दिया गया है:

विकिपीडिया : SQL मानक स्पष्ट रूप से नल के लिए एक डिफ़ॉल्ट क्रम को परिभाषित नहीं करता है। इसके बजाय, सिस्टम के अनुरूप होने पर, नल को क्रमशः डेटा सूची के NULLS FIRST या NULLS LAST क्लॉज का उपयोग करके सभी डेटा मानों से पहले या बाद में सॉर्ट किया जा सकता है। हालांकि सभी डीबीएमएस विक्रेता इस कार्यक्षमता को लागू नहीं करते हैं। इस कार्यक्षमता को लागू नहीं करने वाले विक्रेता DBMS में नल छँटाई के लिए अलग-अलग उपचार निर्दिष्ट कर सकते हैं।


तो, यह एक निर्णय कॉल है। यह काफी काम की बात है। धन्यवाद!
रिचर्ड

6

आप सही हैं कि NULL'Indeterminant' या 'Uknownn' या 'अभी तक ज्ञात नहीं' या 'लागू नहीं' का अर्थ हो सकता है। लेकिन नल को पहले या आखिरी में लगाने का कोई कारण नहीं है। यदि हम वास्तविक मूल्यों को नहीं जानते हैं, तो छोटे या बड़े हो सकते हैं।

मुझे लगता है कि छँटाई के दौरान नल के वांछित व्यवहार को निर्धारित करने के लिए मानक है:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

दुर्भाग्य से SQL- सर्वर ने इस सिंटैक्स को अभी तक नहीं अपनाया है। अगर मैं गलत नहीं हूँ PostgreSQL और Oracle यह है।

एक हल:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

डेटाटाइप के आधार पर समायोजन के लिए एक और समाधान - लेकिन अच्छी तरह से पूर्ववर्ती नहीं होगा, क्योंकि यह एक सूचकांक का उपयोग नहीं कर सकता है (test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer

इस तरह ORDER BY COALESCE (परीक्षण, 2147483647) SQL सर्वर इंडेक्स का उपयोग नहीं कर सकता है।
अर्दलन शहघोली

3

मुझे नहीं पता कि ऐसा क्यों किया गया है, लेकिन परिभाषा के अनुसार NULLS की तुलना गैर-NULLS से नहीं की जा सकती है, इसलिए उन्हें या तो शुरुआत या अंत में जाना होगा (मार्क का उत्तर इसे और अधिक विस्तार से कवर करता है)।

आप जो व्यवहार चाहते हैं, उसे प्राप्त करने के लिए - जहाँ तक मुझे पता है कि अंतिम नल लगाने के लिए कोई छँटाई का विकल्प नहीं है, इसलिए आपको उन्हें बाध्य करने के लिए एक गणना किए गए कॉलम का उपयोग करके इसे चकमा देना होगा। हालाँकि, SQL सर्वर में आप एक गणना किए गए कॉलम ( CASE WHEN ...) द्वारा ऑर्डर नहीं कर सकते हैं जब आपके डेटा में एक सेट ऑपरेटर होता है ( UNION ALL)। इसलिए:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

पिछले nulls छँटाई के लिए काम करेंगे। आप उपयोग करना है, तो UNION(या EXCEPTया INTERSECTS) अपने डेटा सेट उत्पन्न करने के लिए है, तो इसके बाद के संस्करण के रूप में एक अस्थायी तालिका के लिए अपने डेटा डंप।


... या व्युत्पन्न तालिका के रूप में UNIONed आउटपुट का उपयोग करें।
एंड्री एम

0

यदि आप संख्याओं के साथ काम कर रहे हैं तो आप इसका उपयोग भी कर सकते हैं

ORDER BY -test DESC

NULLसबसे कम संभव मान हैं, इसलिए DESCउन्हें अंत में रखता है। इस बीच शून्य मानों में हस्ताक्षर उलटे नहीं होते हैं इसलिए DESCवास्तव ASCमें वास्तविक मूल्यों पर होता है। इससे अधिक तेज़ होना चाहिए CASEऔर मुझे लगता है कि क्वेरी ऑप्टिमाइज़र testकॉलम पर अनुक्रमित का भी उपयोग कर सकता है ।


3
नहीं, यह सॉर्ट के लिए एक इंडेक्स का उपयोग करने में सक्षम नहीं होगा। जब तक आपके पास गणना की गई अभिव्यक्ति पर एक सूचकांक नहीं है (- test)
ypercube y

1
चतुर, भले ही केवल संख्यात्मक डेटा तक सीमित हो (वैसे भी ओपी के उदाहरण के लिए उपयुक्त)। मुझे यकीन नहीं है कि यह वास्तव में CASE का उपयोग करने की तुलना में तेज़ होगा, लेकिन मुझे यकीन है कि यह एक सूचकांक का उपयोग नहीं करेगा (जब तक कि यह @ ypercube then नहीं कहता - लेकिन फिर एक CASE अभिव्यक्ति को उसी तरह अनुक्रमित किया जा सकता है)।
एंड्री एम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.