2011-09-07 6 views
7

Esiste qualche differenza tra l'inserimento di predicati aggiuntivi in ​​un'istruzione JOIN e l'aggiunta di questi come clausole aggiuntive nell'istruzione WHERE?T-SQL: predicati aggiuntivi su JOINs rispetto alla clausola WHERE

Esempio 1: predicato sulla clausola WHERE

select emp.* 
from Employee emp 
left join Order o on emp.Id = o.EmployeeId 
where o.Cancelled = 0 

Esempio 2: predicato sulla privacy Iscrizione

select emp.* 
from Employee emp 
left join Order o on emp.Id = o.EmployeeId and o.Cancelled = 0 

risposta

3

ho già avuto le risposte da alcuni dei miei colleghi, ma nel caso non lo pubblichino qui, aggiungerò una risposta da solo.

Entrambi questi esempi presuppongono che il predicato stia confrontando una colonna sulla tabella "destra" con un valore scalare.

prestazioni
Sembra che se il predicato è sul JOIN, quindi la tabella "giusta" viene filtrata in anticipo. Se il predicato fa parte della clausola WHERE, tutti i risultati tornano e vengono filtrati una volta alla fine prima di restituire il gruppo di risultati.

dati restituiti
se il predicato è parte della clausola WHERE, quindi nella situazione in cui il valore "giusto" è nullo (cioè non v'è alcuna riga giunzione) allora l'intera riga non saranno restituiti nel set di risultati finale, in quanto il predicato confronta il valore con null e pertanto restituisce false.

+0

corretti diversi risultati possono essere restituiti, ma penso che ha davvero bisogno alcuni dati di esempio che mostrano questo. –

+0

Sì, stavo cercando di evitare di usare le parole "corretto" o "errato", perché in realtà sono solo diversi. Potrebbe essere che uno * desideri * restituire solo i record in cui vi è una corrispondente riga "destra" con il predicato soddisfatto. –

+3

Se si desidera restituire solo i record in corrispondenza di una riga "destra" corrispondente, è necessario utilizzare un JOIN (o INNER JOIN per utilizzare la sintassi completa). L'utilizzo di LEFT JOIN invia messaggi in conflitto a qualcuno che sta leggendo la query e non è chiaro cosa dovrebbe fare la query. – JonPayne

8

Con la prima istruzione il join esterno viene effettivamente trasformato in un inner join a causa della condizione WHERE poiché filtra tutte le righe dalla tabella dei dipendenti in cui non è stato trovato alcun ordine (perché o.Cancelled sarà NULL quindi)

Quindi le due dichiarazioni non fanno la stessa cosa.

3

Solo per risolvere il caso in cui il predicato aggiuntivo si trova su una colonna dalla tabella di sinistra, questo può comunque fare la differenza, come mostrato di seguito.

WITH T1(N) AS 
(
SELECT 1 UNION ALL 
SELECT 2 
), T2(N) AS 
(
SELECT 1 UNION ALL 
SELECT 2 
) 
SELECT T1.N, T2.N, 'ON' AS Clause 
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N AND T1.N=1 
UNION ALL 
SELECT T1.N, T2.N, 'WHERE' AS Clause 
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N 
WHERE T1.N=1 

Returns

N   N   Clause 
----------- ----------- ------ 
1   1   ON 
2   NULL  ON 
1   1   WHERE 
0

Ecco un altro esempio (quattro casi)

insert into #tmp(1,"A") 
insert into #tmp(2,"B") 

select "first Query", a.*,b.* from #tmp a LEFT JOIN #tmp b 
on a.id =b.id 
and a.id =1 

union all 

select "second Query", a.*,b.* from #tmp a LEFT JOIN #tmp b 
on a.id =b.id 
where a.id =1 

union all 

select "Third Query", a.*,b.* from #tmp a LEFT JOIN #tmp b 
on a.id =b.id 
and b.id =1 

union all 

select "Fourth Query", a.*,b.* from #tmp a LEFT JOIN #tmp b 
on a.id =b.id 
where b.id =1 

Risultati:

first Query  1  A  1  A 
first Query  2  B  NULL NULL 
second Query  1  A  1  A 
Third Query  1  A  1  A 
Third Query  2  B  NULL NULL 
Fourth Query  1  A  1  A 
Fourth Query  1  A  1  A