क्यों एक उपश्रेणी के भीतर बिक्री NULL देता है?


15

इस स्कीमा को देखते हुए:

CREATE TABLE #TEST_COALESCE
(
    Id int NOT NULL,
    DateTest datetime NOT NULL,
    PRIMARY KEY (Id, DateTest)
);

INSERT INTO #TEST_COALESCE VALUES
(1, '20170201'),
(1, '20170202'),
(1, '20170203'),
(2, '20170204'),
(2, '20170205'),
(2, '20170206');

यदि मैं किसी उपश्रेणी के भीतर COALESCE का उपयोग करता हूं, तो यह NULL देता है।

SELECT  t1.Id, t1.DateTest,
        (SELECT TOP 1 COALESCE(t2.DateTest, t1.DateTest)
         FROM         #TEST_COALESCE t2
         WHERE        t2.Id = t1.Id
         AND          t2.DateTest > t1.DateTest
         ORDER BY     t2.Id, t2.DateTest) NextDate
FROM    #TEST_COALESCE t1;

+----+---------------------+---------------------+
| Id | DateTest            | NextDate            |
+----+---------------------+---------------------+
| 1  | 01.02.2017 00:00:00 | 02.02.2017 00:00:00 |
| 1  | 02.02.2017 00:00:00 | 03.02.2017 00:00:00 |
| 1  | 03.02.2017 00:00:00 | NULL                |
| 2  | 04.02.2017 00:00:00 | 05.02.2017 00:00:00 |
| 2  | 05.02.2017 00:00:00 | 06.02.2017 00:00:00 |
| 2  | 06.02.2017 00:00:00 | NULL                |
+----+---------------------+---------------------+

हालांकि, अगर यह उपकुंजी के बाहर रखा गया है:

SELECT  t1.Id, t1.DateTest,
        COALESCE((SELECT TOP 1 t2.DateTest
                 FROM         #TEST_COALESCE t2
                 WHERE        t2.Id = t1.Id
                 AND          t2.DateTest > t1.DateTest
                 ORDER BY     t2.Id, t2.DateTest), t1.DateTest) NextDate
FROM    #TEST_COALESCE t1;

+----+---------------------+---------------------+
| Id | DateTest            | NextDate            |
+----+---------------------+---------------------+
| 1  | 01.02.2017 00:00:00 | 02.02.2017 00:00:00 |
| 1  | 02.02.2017 00:00:00 | 03.02.2017 00:00:00 |
| 1  | 03.02.2017 00:00:00 | 03.02.2017 00:00:00 |
| 2  | 04.02.2017 00:00:00 | 05.02.2017 00:00:00 |
| 2  | 05.02.2017 00:00:00 | 06.02.2017 00:00:00 |
| 2  | 06.02.2017 00:00:00 | 06.02.2017 00:00:00 |
+----+---------------------+---------------------+

पहला उपश्रम क्यों नहीं लौटता है t1.DateTest:?

http://rextester.com/CNDOO40877


3
डेमो तालिका और रास्ते में एक रिप्रो क्वेरी का अत्यधिक उपयोग। मैं एक उत्तर पोस्ट नहीं करने जा रहा था, लेकिन फिर मैं चला गया, "उसने यह सब काम सवाल में डाल दिया, कम से कम मैं कुछ काम कर सकता हूं, एक जवाब में, हाहाहा।"
ब्रेंट ओजर

हाय @BrentOzar, आपके विस्तृत उत्तर के लिए धन्यवाद, यह स्पष्ट है।
मैकनेट्स

जवाबों:


16

चयन में चीजें केवल तभी लौटा दी जाती हैं जब FROM विवरण में दी गई पंक्तियाँ होती हैं।

पहले, आइए इसे वैचारिक रूप से सोचें।

प्रश्न 1 इस प्रकार है:

"जाओ अपने गैरेज में सभी फेरारिस ढूंढो। प्रत्येक फेरारी के लिए, मुझे लाइसेंस प्लेट नंबर दो, या यदि इसके पास प्लेट नंबर नहीं है, तो मुझे 'नो फ़ेर्रिस फ़ाउंड' दें।"

क्वेरी बिना पंक्तियों के साथ वापस आ जाएगी - क्योंकि गैरेज में फेरारी नहीं थी। (कम से कम, मेरे अपने गेराज में कोई पंक्तियाँ नहीं मिलीं।)

क्वेरी 2 अलग है:

"गैरेज में जाओ। अगर आपको फेरारी पर लाइसेंस प्लेट मिल जाए, तो मुझे वह दे दो - अन्यथा, मुझे 'नो फ़ेरिश फ़ाउंड' दें।"

इसीलिए तलाशी अभियान से बाहर रहना पड़ता है: परिणाम में कोई पंक्तियाँ न होने पर भी आपको ऐसा करने की आवश्यकता होती है।

अब, अपनी क्वेरी को देखें।

मैं अपने दम पर सबकुछ लेने जा रहा हूं, और मैं उन पंक्तियों में से एक के लिए हार्ड-कोड मान जा रहा हूं, जहां आप चाहते हैं कि COALESCE काम करे, लेकिन यह नहीं हो सकता:

SELECT TOP 1 COALESCE(t2.DateTest, 'NO FERRARIS FOUND')
     FROM         #TEST_COALESCE t2
     WHERE        t2.Id = 1
     AND          t2.DateTest > '2017-02-03 00:00:00.000'
     ORDER BY     t2.Id, t2.DateTest

WHERE क्लॉज में, मैंने हार्ड-कोडित Id = 1 और DateTest> '2017-02-03 00: 00: 00.000' लिखी है। जब यह क्वेरी चलती है, तो इसका कोई परिणाम नहीं मिलता है:

कोई फेरारी नहीं मिला

इसलिए COALESCE काम नहीं करता है: इस परिणाम सेट में कोई पंक्तियाँ नहीं थीं, और आपके गेराज में कोई फेरारी नहीं थी। मास्टर कि अवधारणा, और आप में फेरारीस होगा ... एक मिनट रुको ... मुझे उस अवधारणा में महारत हासिल है, और मेरे गैरेज में फेरारी नहीं हैं ...


3
हाहाहा, ध्यान से देखिए, क्या आपको यकीन है कि वहाँ कोई 360 मोडेना नहीं है?
मैकनेट्स

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