하위 쿼리 내의 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
그건 그렇고 데모 테이블과 repro 쿼리의 탁월한 사용. 나는 대답을 게시하지 않을 것이지만 "그는이 모든 작업을 질문에 넣었습니다. 제가 할 수있는 최소한의 작업은 답에 답하는 것입니다."
브렌트 오자르

안녕하세요 @BrentOzar, 자세한 답변 주셔서 감사합니다, 그것은 분명하다.
McNets

답변:


16

FROM 문에 행이 리턴 된 경우에만 select의 항목이 리턴됩니다.

먼저 개념적으로 생각해 봅시다.

쿼리 1은 다음과 같습니다.

"차고에서 모든 페라리를 찾으십시오. 각 페라리마다 번호판 번호를 알려주십시오. 또는 번호판 번호가없는 경우 'NO FERRARIS FOUND'를주십시오."

차고에 페라리가 없기 때문에 쿼리가 행없이 다시 나타납니다. (적어도 내 차고에는 행이 없었습니다.)

쿼리 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

WHERE 절에서 Id = 1로 하드 코딩했으며 DateTest> '2017-02-03 00 : 00 : 00.000'입니다. 이 쿼리가 실행되면 결과가 반환되지 않습니다.

페라리를 찾을 수 없습니다

이것이 COALESCE가 작동하지 않는 이유입니다.이 결과 집합에 행이없고 차고에 Ferraris가 없습니다. 그 개념을 마스터하면, 당신은 당신의 페라리를 가질 것입니다 ... 잠시만 요 ... 나는 그 개념을 마스터했고, 내 차고에는 페라리가 없습니다 ...


3
하하하, 조심해, 거기에 360 모데나 가 없습니까?
McNets

3
@McNets 아마 안전하기 위해 다시 확인해야합니다.
브렌트 오자르
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.