it-swarm.com.de

Warum gibt COALESCE innerhalb einer Unterabfrage NULL zurück?

Angesichts dieses Schemas:

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

Wenn ich COALESCE in einer Unterabfrage verwende, wird NULL zurückgegeben.

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

Wenn es jedoch außerhalb der Unterabfrage platziert wird:

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

Warum die erste Unterabfrage nicht zurückgibt: t1.DateTest?

http://rextester.com/CNDOO40877

15
McNets

Dinge in der Auswahl werden nur zurückgegeben, wenn in der FROM-Anweisung Zeilen zurückgegeben werden.

Lassen Sie uns zunächst konzeptionell darüber nachdenken.

Abfrage 1 lautet wie folgt:

"Suchen Sie alle Ferraris in Ihrer Garage. Geben Sie mir für jeden Ferrari das Kennzeichen, oder geben Sie mir 'NO FERRARIS FOUND', wenn er kein Kennzeichen hat."

Die Abfrage würde ohne Zeilen zurückkommen - weil kein Ferrari in der Garage war. (Zumindest wurden in meiner eigenen Garage keine Reihen gefunden.)

Abfrage 2 ist anders:

"Gehen Sie in die Garage. Wenn Sie ein Nummernschild auf einem Ferrari finden, geben Sie mir das - andernfalls geben Sie mir 'NO FERRARIS FOUND'."

Aus diesem Grund muss die Koaleszenz außerhalb des Suchvorgangs liegen: Sie muss auch dann erfolgen, wenn die Ergebnismenge keine Zeilen enthält.

Schauen wir uns nun Ihre Anfrage an.

Ich werde die Unterabfrage selbst herausnehmen und Werte für eine der Zeilen, in denen COALESCE funktionieren soll, hart codieren, aber es kann nicht:

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

In der WHERE-Klausel habe ich ID = 1 und DateTest> '2017-02-03 00: 00: 00.000' fest codiert. Wenn diese Abfrage ausgeführt wird, werden keine Ergebnisse zurückgegeben:

(No Ferraris found

Deshalb funktioniert der COALESCE nicht: Diese Ergebnismenge enthielt keine Zeilen und keine Ferraris in Ihrer Garage. Beherrsche dieses Konzept und du wirst Ferraris in deinem ... Moment mal ... Ich habe dieses Konzept gemeistert und es gibt keine Ferraris in meiner Garage ...

16
Brent Ozar