为什么子查询中的 COALESCE 返回 NULL?

McN*_*ets 15 sql-server

鉴于此架构:

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');
Run Code Online (Sandbox Code Playgroud)

如果我在子查询中使用 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                |
+----+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

但是,如果它放在子查询之外:

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 |
+----+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

为什么第一个子查询不返回:t1.DateTest

http://rextester.com/CNDOO40877

Bre*_*zar 16

只有在 FROM 语句中返回了行时,才返回 select 中的内容。

首先,让我们从概念上考虑它。

查询 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
Run Code Online (Sandbox Code Playgroud)

在 WHERE 子句中,我硬编码了 Id = 1 和 DateTest > '2017-02-03 00:00:00.000'。当此查询运行时,它不返回任何结果:

没有找到法拉利

这就是 COALESCE 不起作用的原因:此结果集中没有行,您的车库中也没有法拉利。掌握这个概念,你就会有法拉利......等一下......我已经掌握了这个概念,我的车库里没有法拉利......

  • 哈哈哈,仔细看,确定没有【360 Modena】(http://auto.ferrari.com/en_EN/sports-cars-models/past-models/360-modena/)吗? (3认同)
  • @McNets 为了安全起见,我可能应该再去检查一下。 (3认同)