질문:
declare @X xml = '
<item ID = "0"/>
<item ID = "1"/>
<item/>
<item/>';
select I.X.value('@ID', 'int')
from @X.nodes('/item') as I(X);
결과:
-----------
0
1
NULL
NULL
실행 계획 :
맨 위 분기는 XML을 4 개의 행으로 분리하고 맨 아래 분기는 속성 값을 가져옵니다 ID
.
이상한 점은 Stream Aggregate 연산자에서 반환 된 행 수입니다. 필터에서 나오는 2 개의 행 은 XML ID
의 첫 번째 item
노드 와 두 번째 노드 의 속성입니다 . 스트림 집계는 입력 행마다 하나씩 4 개의 행을 반환하여 내부 조인을 외부 조인으로 효과적으로 전환합니다.
이것이 Stream Aggregate가 다른 상황에서도 수행하는 것입니까, 아니면 XML 쿼리를 수행 할 때 이상한 일입니까?
XML 버전의 쿼리 계획에서이 Stream Aggregate가 이전에 주목 한 다른 Stream Aggregate와 다르게 동작해야한다는 힌트를 볼 수 없습니다.
답변
집계는 스칼라 집계입니다 (그룹 별 절 없음). 입력이 비어 있어도 항상 행을 생성하도록 SQL Server에 정의됩니다.
A의 스칼라 집계, MAX
이다없는 행으로 NULL
, COUNT
어떤 행의 예를 들면, 제로이다. 옵티마이 저는이 모든 것을 알고 있으며 적절한 상황에서 외부 조인을 내부 조인으로 변환 할 수 있습니다.
-- NULL for a scalar aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2;
-- No row for a vector aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2 GROUP BY ();
집계에 대한 자세한 내용은 내 기사 Scalar 및 Vector Aggregates를 참조하십시오 .
답변
여기서 기억해야 할 것은 실행 계획이 데이터를 빨아 들인다는 것입니다.
따라서 Nested Loop 연산자는 Stream Aggregate를 4 번 호출합니다. 스트림 집계는 필터를 4 번 호출하지만 값은 두 번만 가져옵니다.
따라서 스트림 집계는 네 가지 값을 제공합니다. 두 번 값을 제공하고 두 번 Null을 제공합니다.