为什么左连接导致NEWID()比加入更快实现?

Joh*_*ohn 5 sql t-sql sql-server

使用MSSQL Server 2008企业版,以及很可能是其他版本的MSSQL,这里是一个概念证明,它使得临时表和具体化的NEWID()取决于您是否使用了JOIN或LEFT JOIN,即使我们匹配两行究竟.

如果查看执行计划,可以看到使用JOIN最后执行获取NEWID()的计算标量,但在使用LEFT JOIN时则不会.我原本期望LEFT JOIN行为.这种怪异是由于执行计划中的天真还是还有更多的事情发生?

Temp表的演示:

Create Table #Temp
(
    ChildGuid uniqueidentifier,
    ParentGuid uniqueidentifier
)
insert into #Temp (ChildGuid, ParentGuid) Values('5E3211E8-D382-4775-8F96-041BF419E70F', '96031FA0-829F-43A1-B5A6-108362A37701')
insert into #Temp (ChildGuid, ParentGuid) Values('FFFFFFFF-D382-4775-8F96-041BF419E70F', '96031FA0-829F-43A1-B5A6-108362A37701')

--Use a join. Get different NewIDs.
select * from #Temp 
join 
(
    select ParentGuid, NewParentGuid from(
    select ParentGuid, NEWID() as NewParentGuid from #Temp
    group by ParentGuid
    ) tb2
) temp2 on #Temp.ParentGuid = temp2.ParentGuid

--Do exactly as above, but use a left join. Get a pair of the same NewIDs.
select * from #Temp 
left join 
(
    select ParentGuid, NewParentGuid from(
    select ParentGuid, NEWID() as NewParentGuid from #Temp
    group by ParentGuid
    ) tb2
) temp2 on #Temp.ParentGuid = temp2.ParentGuid
Run Code Online (Sandbox Code Playgroud)

使用Join,NewParentGuid对于两行都不同.

使用Left Join,NewParentGuid是相同的.

编辑2:如果将此附加到左连接,结果将更改.

where temp2.ParentGuid = temp2.ParentGuid
Run Code Online (Sandbox Code Playgroud)

或者正如另一位用户指出的那样,该列不为null.在其他列或1 = 1.Schroedinger的列上进行比较时,它们将保持不变?

也可以看看:

为什么newid()在查询的最后实现?

HLG*_*GEM 0

我不知道为什么它会在内部联接的查询结束时实现,但是如果您像这样在其上放置一个 where 子句(有效地将其更改为内部联接),则左联接的行为也会发生变化

select * from #Temp 
left join 
(
    select ParentGuid, NewParentGuid from(
    select ParentGuid, NEWID() as NewParentGuid from #Temp
    group by ParentGuid
    ) tb2
) temp2 on #Temp.ParentGuid = temp2.ParentGuid
where temp2.ParentGuid is not null
Run Code Online (Sandbox Code Playgroud)

它可能对任何 where 子句执行此操作。嗯,如果您希望 GUID 在上面的左连接条件下按预期工作,最安全的做法是完全在选择之外执行派生表并将结果放入临时表中。那么以后的维护就不会意外地改变它的工作方式。