2012-08-30 3 views
10

He estado teniendo dificultades para buscar en Google una respuesta para esto, pero ... alguien puede explicarme la diferencia entre poner la condición ON de un JOIN con el JOIN en sí mismo frente a poner el ON al final de todas las demás JOINs.En SQL, ¿cuál es la diferencia una condición ON después de una combinación vs al final de múltiples UNE

aquí es un ejemplo http://sqlfiddle.com/#!3/e0a0f/3

CREATE TABLE TableA (Email VARCHAR(100), SomeNameA VARCHAR(100)) 
CREATE TABLE Tableb (Email VARCHAR(100), SomeNameB VARCHAR(100)) 
CREATE TABLE Tablec (Email VARCHAR(100), SomeNameC VARCHAR(100)) 

INSERT INTO TableA SELECT '[email protected]', 'JoeA' 
INSERT INTO TableA SELECT '[email protected]', 'JaneA' 
INSERT INTO TableA SELECT '[email protected]', 'DaveA' 
INSERT INTO TableB SELECT '[email protected]', 'JoeB' 
INSERT INTO TableB SELECT '[email protected]', 'DaveB' 
INSERT INTO TableC SELECT '[email protected]', 'JoeC' 
INSERT INTO TableC SELECT '[email protected]', 'DaveC' 


SELECT TOP 2 a.*, 
      b.*, 
      c.* 
FROM TableA a 
     LEFT OUTER JOIN TableB b 
        ON a.email = b.email 
     INNER JOIN TableC c 
        ON c.Email = b.email; 

SELECT TOP 2 a.*, 
      b.*, 
      c.* 
FROM TableA a 
     LEFT OUTER JOIN TableB b 
     INNER JOIN TableC c 
        ON c.Email = b.email 
        ON a.email = b.email; 

No entiendo por qué estas dos instrucciones SELECT producen resultados diferentes.

Respuesta

12

Lo que importa son los pedidos de combinaciones. Trate sus expresiones como si cada unión produjera una tabla "virtual" temporal.

Así que cuando se escribe

FROM TableA a 
LEFT OUTER JOIN TableB b ON a.email = b.email 
INNER JOIN TableC c ON c.Email = b.email ; 

entonces el orden es el siguiente:

  1. TableA queda unido a la producción de TableB relación temporal V1
  2. V1 se une a TableC interior.

Meanhwile Cuando se escribe:

FROM TableA a 
LEFT OUTER JOIN TableB b 
INNER JOIN TableC c ON c.Email = b.email ON a.email = b.email; 

orden entonces es la siguiente:

  1. TableB es interno unido a la producción de TableC relación temporal V1.
  2. TableA se ha unido a V1.

Por lo tanto, los resultados son diferentes.En general, se recomienda utilizar paréntesis en tales situaciones para mejorar la legibilidad de la consulta:

FROM TableA a 
LEFT OUTER JOIN 
    (TableB b INNER JOIN TableC c ON c.Email = b.email) 
ON a.email = b.email; 
+0

aplausos por esta explicación exhaustiva – MakkyNZ

4

En su segundo ejemplo, la pieza ON a.email = b.email pertenece al LEFT JOIN.
Si escribe así, significa lo siguiente:

INNER JOIN TableC con TableB y LEFT OUTER JOIN el resultado con TableA.

El resultado serán todas las filas de TableA unidas con aquellas filas de TableB que también tienen una entrada en TableC.

El primer ejemplo significa lo siguiente:

LEFT OUTER JOIN TableB con TableA y INNER JOIN TableC con el resultado. Esto es equivalente a usar un INNER JOIN para TableB.
Explicación: Cuando LEFT OUTER JOIN TableA con TableB obtendrá todas las filas de TableA y para filas coincidentes en TableB obtendrá también esos datos. En su conjunto de resultados, tendrá filas con b.email = NULL y ahora será INNER JOIN ed con TableC. Mientras no haya entrada en TableC con email = NULL, obtendrá los resultados que observó.

Cuestiones relacionadas