询问:
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 分解为四行,底部分支获取属性的值ID
。
让我感到奇怪的是从 Stream Aggregate 运算符返回的行数。来自 Filter 的两行是XML 中ID
第一个和第二个节点的属性。item
Stream Aggregate 返回四行,每个输入行一行,有效地将内部连接转换为外部连接。
这是 Stream Aggregate 在其他情况下也会做的事情,还是在执行 XML 查询时会发生一些奇怪的事情?
我在查询计划的 XML 版本中看不到任何提示,表明此流聚合的行为应该与我之前注意到的任何其他流聚合有任何不同。
聚合是一个标量聚合(没有 group by 子句)。这些在 SQL Server 中定义为始终生成一行,即使输入为空也是如此。
例如,对于标量聚合,
MAX
没有行的是NULL
,COUNT
没有行的是零。优化器知道这一切,并且可以在适当的情况下将外部连接转换为内部连接。有关聚合的更多信息,请参阅我的文章Fun With Scalar and Vector Aggregates。
这里要记住的是,执行计划会吸收数据。
因此,嵌套循环运算符调用流聚合 4 次。Stream Aggregate 也调用了 Filter 4 次,但只获取了一个值两次。
所以 Stream Aggregate 给出了四个值。两次它给出一个值,两次它给出 Null。