Consulta:
declare @X xml = '
<item ID = "0"/>
<item ID = "1"/>
<item/>
<item/>';
select I.X.value('@ID', 'int')
from @X.nodes('/item') as I(X);
Resultado:
-----------
0
1
NULL
NULL
Plano de execução:
A ramificação superior divide o XML em quatro linhas e a ramificação inferior busca o valor do atributo ID
.
O que me parece estranho é o número de linhas retornadas do operador Stream Aggregate. As 2 linhas que vêm do Filtro são os ID
atributos do primeiro e segundo item
nós no XML. O Stream Aggregate retorna quatro linhas, uma para cada linha de entrada, transformando efetivamente o Inner Join em Outer Join.
Isso é algo que o Stream Aggregate também faz em outras circunstâncias ou é apenas algo estranho acontecendo ao fazer consultas XML?
Não consigo ver nenhuma dica na versão XML do plano de consulta de que esse Stream Aggregate deva se comportar de maneira diferente de qualquer outro Stream Aggregate que observei antes.
O agregado é um agregado escalar (sem grupo por cláusula). Estes são definidos no SQL Server para sempre produzir uma linha, mesmo que a entrada esteja vazia.
Para um agregado escalar
MAX
, sem linhas éNULL
,COUNT
sem linhas é zero, por exemplo. O otimizador sabe tudo sobre isso e pode transformar uma junção externa em uma junção interna em circunstâncias adequadas.Para saber mais sobre agregações, consulte meu artigo Fun with Scalar and Vector Aggregates .
O que deve ser lembrado aqui é que os planos de execução sugam os dados.
Portanto, o operador Nested Loop chama o Stream Aggregate 4 vezes. O Stream Aggregate também chama o filtro 4 vezes, mas só obtém um valor duas vezes.
Portanto, o Stream Aggregate fornece quatro valores. Duas vezes dá um valor e duas vezes dá Nulo.