Utilizzo di MSSQL Server 2008 Enterprise Edition e molto probabilmente altre versioni di MSSQL, ecco una dimostrazione di concetto che crea una tabella temporanea e materializza NEWID() in modo diverso a seconda se si è utilizzato JOIN o LEFT JOIN, anche se stiamo abbinando due file esattamente.Perché l'unione sinistra fa sì che NEWID() si materializzi prima di unirsi?
Se si guarda il piano di esecuzione, è possibile vedere che lo scalare di calcolo per ottenere NEWID() viene eseguito per ultimo utilizzando JOIN, ma non quando si utilizza LEFT JOIN. Mi sarei aspettato il comportamento LEFT JOIN. Questa stranezza è dovuta all'ingenuità nel piano di esecuzione o c'è qualcosa di più in corso?
Dimostrazione Con Tabella 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
Con Join, NewParentGuid è diverso per entrambe le righe.
Con Join a sinistra, NewParentGuid è la stessa.
EDIT2: se si aggiunge questo al join di sinistra, i risultati cambiano.
where temp2.ParentGuid = temp2.ParentGuid
O come altro utente indicate, ove tale colonna non è nullo. Rimarranno gli stessi quando si effettuano confronti su altre colonne o dove 1 = 1. colonna di Schroedinger?
Consulta anche:
Why does newid() materialize at the very end of a query?
Questo è così strano, mi sarei aspettato il LEFT JOIN risultato in entrambi i casi poiché hai solo un id genitore. D'altra parte non è necessario alcun codice se si vogliono newguid separati. Perché no: seleziona *, NEWID() come NewParentGuid da #Temp – HLGEM
Sono stato sorpreso di vedere anche il comportamento JOIN, mentre mi aspettavo che si comportasse come il LEFT JOIN, quindi ho aggiornato il mio post per menzionarlo. – John
Uno è un join hash e l'altro un join di tipo merge ma se si impone che entrambi siano uguali, i risultati sono gli stessi. – Paparazzi