Учитывая эту схему:
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
:?
sql-server
McNets
источник
источник
Ответы:
Вещи в select возвращаются, только если в операторе FROM возвращены строки.
Во-первых, давайте подумаем об этом концептуально.
Запрос 1 похож на:
Запрос вернется без строк - потому что в гараже не было Ferrari. (По крайней мере, в моем собственном гараже не было никаких рядов.)
Запрос 2 отличается:
Вот почему объединение должно быть за пределами операции поиска: это необходимо, даже если в наборе результатов нет строк.
Теперь давайте посмотрим на ваш запрос.
Я собираюсь вывести подзапрос самостоятельно, и я собираюсь жестко кодировать значения для одной из строк, где вы хотите, чтобы COALESCE работал, но он не может:
В предложении WHERE я жестко закодировал Id = 1 и DateTest> '2017-02-03 00: 00: 00.000'. Когда этот запрос выполняется, он не возвращает результатов:
Вот почему COALESCE не работает: в этом наборе результатов не было строк, и в вашем гараже не было Ferrari. Освойте эту концепцию, и у вас будет Ferrari в вашем ... подождите минуту ... Я освоил эту концепцию, и в моем гараже нет Ferrari ...
источник