Bir alt sorgudaki COALESCE neden NULL döndürüyor?


15

Bu şema göz önüne alındığında:

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');

Bir alt sorgu içinde COALESCE kullanırsanız, NULL döndürür.

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                |
+----+---------------------+---------------------+

Ancak, alt sorgunun dışına yerleştirilirse:

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 |
+----+---------------------+---------------------+

İlk alt sorgu neden geri dönmüyor t1.DateTest?

http://rextester.com/CNDOO40877


3
Bu arada, bir demo tablosu ve repro sorgusunun MÜKEMMEL kullanımı. Ben bir cevap göndermeyecektim, ama sonra gittim, "Bütün bu çalışmaları soruya soktu, yapabildiğim en az şey bir cevaba biraz iş koymak, hahaha."
— Brent Ozar

Merhaba @BrentOzar, detaylı cevabınız için teşekkürler, kristal berraklığında.
— McNets

Yanıtlar:


16

Seçimdeki şeyler yalnızca FROM deyiminde döndürülen satırlar varsa döndürülür.

İlk olarak, kavramsal olarak düşünelim.

Sorgu 1 şöyle:

"Git garajında ​​tüm Ferraris'i bul. Her Ferrari için bana plaka numarasını ver yoksa plaka numarası yoksa bana 'FERRARİS BULUNAMADI' ver."

Sorgu satır olmadan geri gelecekti - çünkü garajda bir Ferrari yoktu. (En azından kendi garajımda hiç satır bulunamadı.)

Sorgu 2 farklıdır:

"Garaja git. Eğer Ferrari'de bir plaka bulursan, bana şunu ver - yoksa bana 'FERRARİS BULUNAMADI' ver."

Bu nedenle birleşmenin arama işleminin dışında olması gerekir: sonuç kümesinde hiç satır olmasa bile gerçekleşmesi gerekir.

Şimdi sorgunuza bakalım.

Alt sorguyu tek başına çıkaracağım ve COALESCE'ın çalışmasını istediğiniz satırlardan biri için sabit kod değerlerine gideceğim, ancak yapamaz:

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 yan tümcesinde, sabit kodlanmış Id = 1 ve DateTest> '2017-02-03 00: 00: 00.000' kodlarını kullandım. Bu sorgu çalıştırıldığında hiçbir sonuç döndürmez:

Ferraris bulunamadı

İşte bu yüzden COALESCE çalışmıyor: Bu sonuç kümesinde hiç satır ve garajınızda Ferraris yoktu. Bu konsepte hakim olursanız, Ferraris'inizde ... bir dakika bekleyin ... Bu konsepte hakim oldum ve garajımda Ferraris yok ...


3
Hahaha, dikkatle bak, orada 360 Modena olmadığından emin misin ?
— McNets

3
@McNets Muhtemelen tekrar güvende olmak için tekrar kontrol etmeliyim.
— Brent Ozar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.