Unión externa izquierda usando + signo en Oracle 11g


81

¿Alguien puede decirme si las siguientes 2 consultas son un ejemplo de Unión externa izquierda o Unión externa derecha?

Table Part:
Name         Null?       Type
PART_ID      NOT NULL    VARCHAR2(4)
SUPPLIER_ID              VARCHAR2(4)

PART_ID SUPPLIER_ID
P1      S1
P2      S2
P3  
P4  

Table Supplier:
Name            Null?     Type
SUPPLIER_ID NOT NULL      VARCHAR2(4)
SUPPLIER_NAME   NOT NULL  VARCHAR2(20)

SUPPLIER_ID  SUPPLIER_NAME
S1           Supplier#1
S2           Supplier#2
S3           Supplier#3

Mostrar todas las piezas independientemente de si algún proveedor las suministra o no:

SELECCIONE P.Part_Id, S.Proveedor_Name
DESDE la Parte P, Proveedor S
DONDE P.Supplier_Id = S.Supplier_Id (+)

SELECCIONE P.Part_Id, S.Proveedor_Name
DESDE la Parte P, Proveedor S
DONDE S.Supplier_Id (+) = P.Supplier_Id

26
Debe evitar usar la notación '(+)' y actualizar las consultas para usar combinaciones explícitas.
Jonathan Leffler

1
@JonathanLeffler 100% de acuerdo. El problema es que trabajo con personas que no quieren cambiar a la notación estándar. Escribo una nueva consulta con notación estándar, pero dispararé en un minuto si se modifica una anterior.
Luc M

3
@JonathanLeffler Estoy de acuerdo, a menos que esté usando Oracle. Oracle, tal como está actualmente, no maneja la sintaxis ansi tan bien como el operador (+) internamente. Aunque recomiendan usar la sintaxis ansi :) docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
Un mito

7
@Amyth Lo siento por este comentario desactualizado, pero llegué a esta pregunta desde una búsqueda. Por mi parte, entiendo las recomendaciones de Oracle exactamente al revés. Desde su vínculo: " Oracle recomienda que utilice la sintaxis FROM cláusula OUTER JOIN en lugar del operador de combinación de Oracle. Las consultas de combinación externa que utilizan el operador de combinación de Oracle (+) están sujetas a las siguientes reglas y restricciones, que no se aplican a la FROM cláusula OUTER JOIN sintaxis ... "
Sylvain Leroux

Perdón por la respuesta desactualizada también :), pero lo que dice Oracle y cómo funcionan sus estadísticas para optimizar las consultas son dos cosas diferentes, y podría ser que Oracle también haya cambiado su postura con los avances en sus optimizadores internos
un mito

Respuestas:


188

TableA LEFT OUTER JOIN TableBes equivalente a TableB RIGHT OUTER JOIN Table A.

En Oracle, (+)denota la tabla "opcional" en JOIN. Entonces, en su primera consulta, es un P LEFT OUTER JOIN S. En su segunda consulta, es S RIGHT OUTER JOIN P. Son funcionalmente equivalentes.

En la terminología, RIGHT o LEFT especifican qué lado de la combinación siempre tiene un registro y el otro lado puede ser nulo. Entonces, en a P LEFT OUTER JOIN S, Psiempre tendrá un registro porque está en LEFT, pero Spodría ser nulo.

Consulte este ejemplo de java2s.com para obtener una explicación adicional.


Para aclarar, supongo que estoy diciendo que la terminología no importa, ya que solo está ahí para ayudar a visualizar. Lo que importa es que comprenda el concepto de cómo funciona.


DERECHA vs IZQUIERDA

He visto cierta confusión sobre lo que importa al determinar DERECHA frente a IZQUIERDA en la sintaxis de unión implícita.

IZQUIERDA COMBINACIÓN EXTERNA

SELECT *
FROM A, B
WHERE A.column = B.column(+)

UNIÓN EXTERIOR DERECHA

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Todo lo que hice fue cambiar los lados de los términos en la cláusula WHERE, pero siguen siendo funcionalmente equivalentes. (Consulte más arriba en mi respuesta para obtener más información sobre eso). La ubicación de los (+)determina DERECHA o IZQUIERDA. (Específicamente, si (+)está a la derecha, es LEFT JOIN. Si (+)está a la izquierda, es RIGHT JOIN).


Tipos de JOIN

Los dos estilos de JOIN son JOIN implícitos y JOIN explícitos . Son diferentes estilos de escribir JOIN, pero son funcionalmente equivalentes.

Vea esta pregunta SO .

Los JOIN implícitos simplemente enumeran todas las tablas juntas. Las condiciones de unión se especifican en una cláusula WHERE.

JOIN implícito

SELECT *
FROM A, B
WHERE A.column = B.column(+)

Las JOIN explícitas asocian condiciones de combinación con la inclusión de una tabla específica en lugar de en una cláusula WHERE.

JOIN explícito

SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column

Estos JOIN implícitos pueden ser más difíciles de leer y comprender, y también tienen algunas limitaciones, ya que las condiciones de combinación se mezclan en otras condiciones WHERE. Como tal, las JOIN implícitas generalmente se recomiendan en favor de la sintaxis explícita.


3
Bien, lo entiendo ahora: el JOIN se crea implícitamente por la presencia del (+). Frio.
Kerrek SB

2
@Mike: Esa es la forma en que + funciona la sintaxis. Significa "opcional", así que léalo como "Enumere todas las partes, opcionalmente haga coincidir el proveedor".
Kerrek SB

2
@ Mike: Siempre que sepa lo que está seleccionando, realmente no importa cómo lo llame. ¡Pero hazte un favor y usa la JOINsintaxis idiomática en su lugar! Entonces no hay lugar para la confusión.
Kerrek SB

1
@TomJMuthirenthi Sin usar una FULL OUTER JOINsintaxis explícita , necesitará UNION [ALL]dos conjuntos de resultados juntos: uno para A = B (+) y otro para B = A (+). Ejemplo en esta pregunta .
Wiseguy

1
El "(+)" va en las columnas de la tabla que genera subfileras de nulos.
philipxy

9

Estas dos consultas están funcionando OUTER JOIN. Vea abajo

Oracle recomienda que utilice la sintaxis de la cláusula FROM OUTER JOIN en lugar del operador de combinación de Oracle. Las consultas de combinación externa que utilizan el operador de combinación de Oracle (+) están sujetas a las siguientes reglas y restricciones, que no se aplican a la sintaxis de la cláusula FROM OUTER JOIN:

  • No puede especificar el operador (+) en un bloque de consulta que también contiene la sintaxis de combinación de cláusula FROM.

  • El operador (+) puede aparecer solo en la cláusula WHERE o, en el contexto de correlación izquierda (cuando se especifica la cláusula TABLE) en la cláusula FROM, y solo se puede aplicar a una columna de una tabla o vista.

  • Si A y B están unidos por varias condiciones de combinación, debe utilizar el operador (+) en todas estas condiciones. Si no lo hace, Oracle Database devolverá solo las filas resultantes de una combinación simple, pero sin una advertencia o error que le avise que no tiene los resultados de una combinación externa.

  • El operador (+) no produce una combinación externa si especifica una tabla en la consulta externa y la otra tabla en una consulta interna.

  • No puede usar el operador (+) para unir una tabla a sí misma, aunque las autouniones son válidas. Por ejemplo, la siguiente declaración no es válida:

    -- The following statement is not valid:
    SELECT employee_id, manager_id
       FROM employees
       WHERE employees.manager_id(+) = employees.employee_id;
    

    Sin embargo, la siguiente autounión es válida:

    SELECT e1.employee_id, e1.manager_id, e2.employee_id
       FROM employees e1, employees e2
       WHERE e1.manager_id(+) = e2.employee_id
       ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
    
  • El operador (+) se puede aplicar solo a una columna, no a una expresión arbitraria. Sin embargo, una expresión arbitraria puede contener una o más columnas marcadas con el operador (+).

  • Una condición WHERE que contiene el operador (+) no se puede combinar con otra condición usando el operador lógico OR.

  • Una condición WHERE no puede usar la condición de comparación IN para comparar una columna marcada con el operador (+) con una expresión.

Si la cláusula WHERE contiene una condición que compara una columna de la tabla B con una constante, entonces el operador (+) debe aplicarse a la columna para que Oracle devuelva las filas de la tabla A para las que ha generado nulos para esta columna. De lo contrario, Oracle solo devuelve los resultados de una combinación simple.

En una consulta que realiza combinaciones externas de más de dos pares de tablas, una sola tabla puede ser la tabla generada por nulos para otra tabla. Por esta razón, no puede aplicar el operador (+) a las columnas de B en la condición de combinación para A y B y la condición de combinación para B y C. Consulte SELECT para conocer la sintaxis de una combinación externa.

Tomado de http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm


4

Vi algunas contradicciones en las respuestas anteriores, solo probé lo siguiente en Oracle 12c y lo siguiente es correcto:

IZQUIERDA COMBINACIÓN EXTERNA

SELECT *
FROM A, B
WHERE A.column = B.column(+)

UNIÓN EXTERIOR DERECHA

SELECT *
FROM A, B
WHERE B.column(+) = A.column

0

IZQUIERDA COMBINACIÓN EXTERNA

SELECCIONE * DE A, B DONDE A.columna = B.columna (+)

UNIÓN EXTERIOR DERECHA

SELECCIONE * DE A, B DONDE A.columna (+) = B.columna


-2

Hay información incorrecta en este hilo. Copié y pegué la información incorrecta:

IZQUIERDA COMBINACIÓN EXTERNA

SELECT *
FROM A, B
WHERE A.column = B.column(+)

UNIÓN EXTERIOR DERECHA

SELECT *
FROM A, B
WHERE B.column(+) = A.column

¡Lo anterior es INCORRECTO! Es al revés. La forma en que determiné que es incorrecta es del siguiente libro:

Introducción a Oracle OCP a Oracle 9i: Guía de examen de SQL . La Tabla 3-1 tiene un buen resumen sobre esto. ¡No podía entender por qué mi SQL convertido no funcionaba correctamente hasta que fui a la vieja escuela y busqué en un libro impreso!

Aquí está el resumen de este libro, copiado línea por línea:

Sintaxis de unión externa de Oracle:

from tab_a a, tab_b b,                                       
where a.col_1 + = b.col_1                                     

Equivalente a ANSI / ISO:

from tab_a a left outer join  
tab_b b on a.col_1 = b.col_1

Observe aquí que es lo contrario de lo que se publicó anteriormente. Supongo que es posible que este libro tenga erratas, sin embargo confío en este libro más que en lo que está en este hilo. Es una guía de examen para llorar en voz alta ...


4
Esto contradice lo que vinculé en mi respuesta, que es un extracto de Oracle Database 10g SQL (Osborne ORACLE Press Series) 1ra edición (20 de febrero de 2004), que indica: "En una combinación externa izquierda, el operador de combinación externa está en realidad en el derecho del operador de igualdad ". Aquí hay una demostración de su ejemplo . Los resultados de la a.col_1(+) = b.col_1coincidencia RIGHT JOIN, no LEFT JOIN.
Wiseguy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.