サブクエリ内のCOALESCEが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を機能させたい行の1つの値をハードコードしますが、できません。

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念のため、もう一度確認してください。
ブレントオザー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.