使用MSSQL Server 2008企业版,很可能是其他版本的MSSQL,这里有一个概念证明,它使得临时表和具体化的NEWID()取决于你是否使用了JOIN或LEFT JOIN,即使我们是完全匹配两行。
如果查看执行计划,可以看到使用JOIN最后执行获取NEWID()的计算标量,但在使用LEFT JOIN时则不会。我原本期望LEFT JOIN行为。这种怪异是由于执行计划中的天真还是还有更多的事情发生?
使用临时表进行演示:
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
使用Join,NewParentGuid对于两行都不同。
使用Left Join,NewParentGuid是相同的。
EDIT2:如果您将此附加到左侧联接,则结果会更改。
where temp2.ParentGuid = temp2.ParentGuid
或者正如另一位用户指出的那样,该列不为null。在对其他列进行比较时,或者在1 = 1.Schroedinger的列中,它们将保持不变?
另见:
答案 0 :(得分:1)
不是答案,而是观察
这会返回重复的
select * from #Temp
inner hash join
(
select ParentGuid, NEWID() as NewParentGuid
from #Temp
group by ParentGuid
union
select null, NEWID()
) 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 hash join
(
select ParentGuid, NEWID() as NewParentGuid
from #Temp
group by ParentGuid
) temp2
on #Temp.ParentGuid = temp2.ParentGuid
这迫使他们两者不同
select * from #Temp join (
select ParentGuid, NEWID() as NewParentGuid
from #Temp
group by ParentGuid ) 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, NEWID() as NewParentGuid
from #Temp
group by ParentGuid ) temp2
on #Temp.ParentGuid = temp2.ParentGuid
and temp2.ParentGuid is not null
答案 1 :(得分:0)
我不知道为什么它在内部连接的查询结束时实现了,但是如果你像这样放置一个where子句,那么左连接aslo的行为就会改变(有效地将它改为内部加入)
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
对于任何where子句,它可能会这样做。嗯,似乎你希望GUID在上面的左连接条件中按预期工作,最安全的做法是完全选择外部的派生表并将结果放入临时表。然后维护不会意外地改变它的工作方式。