¿Importa el orden de unión en SQL?

189

Sin tener en cuenta el rendimiento, ¿obtendré el mismo resultado de la consulta A y B a continuación? ¿Qué tal C y D?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  
Solo un alumno
fuente
11
¿Qué es <blahblah>? ¿Estás uniendo A a B y A a C, o estás uniendo A a B y B a C?
beny23
2
Hola Beny, el código en mi pregunta es una abstracción. No me preocupa unir A a B o A a C, solo quiero saber si la sintaxis como esa proporcionará resultados idénticos.
Solo un alumno

Respuestas:

225

Para las INNERuniones, no, el orden no importa. Las consultas devolverán los mismos resultados, siempre que cambie sus selecciones de SELECT *a SELECT a.*, b.*, c.*.


Para ( LEFT, RIGHTo FULL) OUTERuniones, sí, el orden importa, y las cosas ( actualizadas ) son mucho más complicadas.

Primero, las uniones externas no son conmutativas, por a LEFT JOIN blo que no es lo mismo queb LEFT JOIN a

Las uniones externas tampoco son asociativas, por lo que en sus ejemplos que involucran ambas propiedades (conmutatividad y asociatividad):

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

es equivalente a :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

pero:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

no es equivalente a :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Otro (con suerte más simple) ejemplo de asociatividad. Piense en esto como (a LEFT JOIN b) LEFT JOIN c:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Esto es equivalente a a LEFT JOIN (b LEFT JOIN c):

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

solo porque tenemos ONcondiciones "agradables" . Ambos ON b.ab_id = a.ab_idy c.bc_id = b.bc_idson controles de igualdad y no implican NULLcomparaciones.

Incluso puede tener condiciones con otros operadores o más complejos como: ON a.x <= b.xo ON a.x = 7o ON a.x LIKE b.xo ON (a.x, a.y) = (b.x, b.y)y las dos consultas seguirían siendo equivalentes.

Sin embargo, si alguno de estos está involucrado IS NULLo una función que está relacionada con valores nulos como COALESCE(), por ejemplo, si la condición era b.ab_id IS NULL, entonces las dos consultas no serían equivalentes.

ypercubeᵀᴹ
fuente
3
Es más correcto decir que la unión externa es asociativa siempre que ninguno de los predicados pueda ser satisfecho por una fila en la que todas las columnas de una tabla son NULL, que decir que es asociativo siempre que los predicados no involucren IS NULL o 'una función que está relacionada con nulos'. Uno puede imaginar fácilmente un predicado que satisfaga la primera descripción pero no la segunda, como a.somecol > 0 OR b.someothercol > 0; la asociatividad podría fallar para esa condición.
Mark Amery
Pero sí, creo que es técnicamente cierto decir que OUTER JOIN es asociativo siempre que el predicado no satisfaga ninguna de las condiciones que describo aquí: stackoverflow.com/questions/20022196/… (el primero de los cuales también rompe la asociatividad para INNER JOINs, pero es un enfoque tan barato y obvio para romperlo que tal vez no valga la pena mencionarlo). También vale la pena señalar que el tipo más común de JOIN, JOIN en una clave externa, no satisface ninguna de esas condiciones y por lo tanto es agradable y asociativo.
Mark Amery
1
@ MarkAmery Gracias, estaba teniendo dificultades para estructurar mis oraciones sobre ese punto (y ya he votado esa respuesta tuya;)
ypercubeᵀᴹ
ypercube tengo un INNER JOINy un siguiente LEFT JOIN. ¿Funciona así primero, la consulta se basará en Filterlos registros INNER JOINy luego se aplicará LEFT JOINa los Filteredregistros?
Muhammad Babar
De hecho, todos los tipos de unión son asociativos, según lo especificado por el estándar SQL y según las definiciones matemáticas de asociatividad, pero no parecen asociativos porque reorganizar los paréntesis requiere mover la ONcláusula (es decir, la "especificación de unión") a una nueva ubicación . Sin embargo, esto es solo sintaxis. Si utiliza la notación de álgebra relacional (donde la especificación de unión se coloca debajo del operador de unión), la asociatividad se vuelve más evidente. Su argumento solo muestra que las uniones externas no son conmutativas , lo cual es correcto
Lukas Eder
4

para uniones regulares, no lo hace. TableA join TableBproducirá el mismo plan de ejecución que TableB join TableA(por lo que sus ejemplos C y D serían los mismos)

para izquierda y derecha se une lo hace. TableA left Join TableBes diferente a TableB left Join TableA, PERO es lo mismo queTableB right Join TableA

Diego
fuente
44
Esto solo aborda la conmutatividad, pero los ejemplos en la pregunta muestran que el autor de la pregunta está interesado en la asociatividad. La respuesta de ypercube se dirige a ambos.
Mark Amery
2

Si intenta unirse a C en un campo desde B antes de unirse a B, es decir:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

su consulta fallará, por lo que en este caso el orden importa.

Teo J.
fuente
Sí, esto es correcto, la respuesta correcta debe ser modificada.
Nir Pengas
-2

Oracle optimizer elige el orden de unión de las tablas para la unión interna. Optimizer elige el orden de unión de las tablas solo en simples cláusulas FROM. Puede consultar la documentación de Oracle en su sitio web. Y para la izquierda, la unión externa derecha, la respuesta más votada es la correcta. El optimizador elige el orden de unión óptimo, así como el índice óptimo para cada tabla. El orden de unión puede afectar qué índice es la mejor opción. El optimizador puede elegir un índice como la ruta de acceso para una tabla si es la tabla interna, pero no si es la tabla externa (y no hay más calificaciones).

El optimizador elige el orden de unión de las tablas solo en cláusulas FROM simples. La mayoría de las combinaciones que usan la palabra clave JOIN se aplanan en combinaciones simples, por lo que el optimizador elige su orden de combinación.

El optimizador no elige el orden de unión para las uniones externas; utiliza el orden especificado en la declaración.

Al seleccionar un orden de unión, el optimizador tiene en cuenta: El tamaño de cada tabla Los índices disponibles en cada tabla Si un índice en una tabla es útil en un orden de unión particular El número de filas y páginas a escanear para cada tabla en cada orden de unión

Saumyojit Das
fuente