2011-09-07 8 views
7

¿Hay alguna diferencia entre colocar predicados adicionales en una sentencia JOIN y agregarlos como cláusulas adicionales en la instrucción WHERE?T-SQL: predicados adicionales sobre JOINs frente a la cláusula WHERE

Ejemplo 1: predicado en la cláusula WHERE

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

Ejemplo 2: Predicado en la instrucción JOIN

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

Respuesta

3

ya tengo las respuestas de algunos de mis colegas, pero en caso de que no lo publiquen aquí, agregaré una respuesta yo mismo.

Ambos ejemplos suponen que el predicado está comparando una columna en la tabla "derecha" con un valor escalar.

Rendimiento
Parece que si el predicado está en el JOIN, entonces la tabla "derecho" se filtra con antelación. Si el predicado es parte de la cláusula WHERE, todos los resultados vuelven y se filtran una vez al final antes de devolver el conjunto de resultados.

datos devueltos
si el predicado es parte de la cláusula WHERE, a continuación, en la situación en la que el valor de "derecho" es nulo (es decir, no hay ninguna fila unión), entonces no será devuelto todo el fila en el resultado final, porque el predicado comparará el valor con null y, por lo tanto, devolverá falso.

+0

resultados correctos diferentes pueden ser devueltos, pero creo que lo que realmente necesita algunos datos de ejemplo que muestran esto. –

+0

Sí, estaba tratando de evitar el uso de las palabras "correcto" o "incorrecto", porque en realidad son simplemente diferentes. Es posible que uno * quiera * solo devolver registros donde haya una fila correspondiente "derecha" con el predicado satisfecho. –

+3

Si solo desea devolver registros donde hay una fila "derecha" correspondiente, se debe usar un JOIN (o INNER JOIN para usar la sintaxis completa). El uso de LEFT JOIN envía mensajes conflictivos a alguien que lee la consulta y no está claro qué se supone que está haciendo la consulta. – JonPayne

8

Con la primera instrucción, la unión externa se convierte efectivamente en una unión interna debido a la condición WHERE, ya que filtrará todas las filas de la tabla de empleados donde no se encontró orden (porque o.Cancer será NULL entonces)

Por lo tanto, las dos afirmaciones no hacen lo mismo.

3

Solo para abordar el caso de que el predicado adicional se encuentre en una columna de la tabla de la izquierda, esto aún puede marcar la diferencia, como se muestra a continuación.

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 

devoluciones

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

Aquí es otro ejemplo (cuatro casos)

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 

Resultados:

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