Diferencia entre INNER JOIN y LEFT SEMI JOIN

82

¿Cuál es la diferencia entre an INNER JOINy LEFT SEMI JOIN?

En el escenario siguiente, ¿por qué obtengo dos resultados diferentes?

El INNER JOINconjunto de resultados es mucho mayor. ¿Alguien puede explicarlo? Estoy tratando de obtener los nombres table_1que solo aparecen en table_2.

SELECT name
FROM table_1 a
    INNER JOIN table_2 b ON a.name=b.name

SELECT name
FROM table_1 a
    LEFT SEMI JOIN table_2 b ON (a.name=b.name)
usuario3023355
fuente
2
La unión interna logrará su objetivo. Nunca había oído hablar de una semiunión hasta que vi esta pregunta.
Dan Bracuk
El left semi joindebe volviendo más filas que el inner join.
Gordon Linoff
1
El inner joindevolverá datos sólo si hay una coincidencia entre las dos tablas. El left joindevolverá datos de la primera tabla sin tener en cuenta si un registro coincidente se encuentra en la segunda tabla.
j03z
11
@GordonLinoff no necesariamente, a LEFT SEMI JOINsolo devolverá una fila desde la izquierda, incluso si hay varias coincidencias en la derecha. An INNER JOINdevolverá varias filas si hay varias coincidencias a la derecha.
D Stanley
1
@ j03z eso no puede ser correcto. Si el propósito de la hemi-unión izquierda es 1) devolver solo la información en la tabla izquierda (como han dicho otros) y 2) devolver filas de la tabla izquierda independientemente de la coincidencia (como creo que dices), entonces eso es solo la tabla izquierda original; no es necesario unir para lograr eso. Creo que otros deben tener razón en que la hemi-unión izquierda 1) solo devuelve columnas de la tabla izquierda, 2) solo devuelve filas que tienen una coincidencia en la tabla derecha y 3) devolverá una sola fila de la izquierda para uno o más partidos.
Carl G

Respuestas:

121

Una INNER JOINpuede devolver datos de las columnas de ambas tablas, y se pueden duplicar los valores de los registros de ambos lados tienen más de una coincidencia. A LEFT SEMI JOINsolo puede devolver columnas de la tabla de la izquierda y produce uno de cada registro de la tabla de la izquierda donde hay una o más coincidencias en la tabla de la derecha (independientemente del número de coincidencias). Es equivalente a (en SQL estándar):

SELECT name
FROM table_1 a
WHERE EXISTS(
    SELECT * FROM table_2 b WHERE (a.name=b.name))

Si hay varias filas coincidentes en la columna de la derecha, an INNER JOINdevolverá una fila por cada coincidencia en la tabla de la derecha, mientras que a LEFT SEMI JOINsolo devuelve las filas de la tabla de la izquierda, independientemente del número de filas coincidentes en el lado derecho. Es por eso que está viendo un número diferente de filas en su resultado.

Estoy tratando de obtener los nombres dentro de table_1 que solo aparecen en table_2.

Entonces a LEFT SEMI JOINes la consulta apropiada para usar.

D Stanley
fuente
¿Existe realmente algo así como un LEFT SEMI JOIN? ¿No es solo un SEMI JOIN? No tiene sentido a RIGHT SEMI JOIN, ¿verdad?
ErikE
En Hive , sí.
D Stanley
1
gran respuesta justo lo que estaba buscando. Yo expresaría la respuesta con mayor precisión: "... un INNER JOIN devolverá una fila por cada fila coincidente de la tabla de la derecha , mientras que un LEFT SEMI JOIN ...
Barak1731475
2
Lo opuesto a esto es un LEFT ANTI JOIN que filtra los datos de la tabla derecha en la tabla izquierda según una clave. ¡Pensé en dejar esta pepita aquí para alguien que pudiera estar buscando!
shantanusinghal
63

Suponga que hay 2 tablas TableA y TableB con solo 2 columnas (Id, Data) y los siguientes datos:

TablaA:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataA11 |
|  1 | DataA12 |
|  1 | DataA13 |
|  2 | DataA21 |
|  3 | DataA31 |
+----+---------+

TablaB:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataB11 |
|  2 | DataB21 |
|  2 | DataB22 |
|  2 | DataB23 |
|  4 | DataB41 |
+----+---------+

La unión interna en la columna Iddevolverá columnas de ambas tablas y solo de los registros coincidentes:

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
'----'---------'----'---------'

La combinación izquierda (o combinación externa izquierda) en la columna Iddevolverá columnas de las tablas y registros coincidentes con registros de la tabla izquierda (valores nulos de la tabla derecha):

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
:----+---------+----+---------:
|  3 | DataA31 |    |         |
'----'---------'----'---------'

La combinación derecha (o combinación externa derecha) en la columna Iddevolverá columnas de las tablas y registros coincidentes con registros de la tabla derecha (valores nulos de la tabla izquierda):

┌────┬─────────┬────┬─────────┐
│ Id │  Data   │ Id │  Data   │
├────┼─────────┼────┼─────────┤
│  1 │ DataA11 │  1 │ DataB11 │
│  1 │ DataA12 │  1 │ DataB11 │
│  1 │ DataA13 │  1 │ DataB11 │
│  2 │ DataA21 │  2 │ DataB21 │
│  2 │ DataA21 │  2 │ DataB22 │
│  2 │ DataA21 │  2 │ DataB23 │
│    │         │  4 │ DataB41 │
└────┴─────────┴────┴─────────┘

La unión externa completa en la columna Iddevolverá columnas de las tablas y registros coincidentes con registros de la tabla izquierda (valores nulos de la tabla derecha) y registros de la tabla derecha (valores nulos de la tabla izquierda):

╔════╦═════════╦════╦═════════╗
║ Id ║  Data   ║ Id ║  Data   ║
╠════╬═════════╬════╬═════════╣
║  - ║         ║    ║         ║
║  1 ║ DataA11 ║  1 ║ DataB11 ║
║  1 ║ DataA12 ║  1 ║ DataB11 ║
║  1 ║ DataA13 ║  1 ║ DataB11 ║
║  2 ║ DataA21 ║  2 ║ DataB21 ║
║  2 ║ DataA21 ║  2 ║ DataB22 ║
║  2 ║ DataA21 ║  2 ║ DataB23 ║
║  3 ║ DataA31 ║    ║         ║
║    ║         ║  4 ║ DataB41 ║
╚════╩═════════╩════╩═════════╝

Left Semi Join en la columna Iddevolverá columnas solo de la tabla izquierda y registros coincidentes solo de la tabla izquierda:

┌────┬─────────┐
│ Id │  Data   │
├────┼─────────┤
│  1 │ DataA11 │
│  1 │ DataA12 │
│  1 │ DataA13 │
│  2 │ DataA21 │
└────┴─────────┘
Abhishek Bansal
fuente
Solía ​​llamar a esto como "Unión INTERIOR IZQUIERDA".
Anshul Joshi
DISTINCT de A. * del resultado INNER JOIN es equivalente a LEFT SEMI JOIN.
Teja
4
Distinto no suena seguro, supongamos que A contiene dos registros idénticos.
Dennis Jaheruddin
Incluso si el resultado termina siendo el mismo, usar DISTINCT podría tener un plan más costoso en comparación con EXISTS
manotheshark
32

Probé en Hive y obtuve el siguiente resultado

tabla 1

1, wqe, chennai, india

2, stu, salem, india

3, mia, bangalore, india

4, yepie, Nueva York, EE. UU.

Tabla 2

1, wqe, chennai, india

2, stu, salem, india

3, mia, bangalore, india

5, chapie, Los Ángeles, EE. UU.

Unir internamente

SELECT * FROM table1 INNER JOIN table2 ON (table1.id = table2.id);

1 wqe chennai india 1 wqe chennai india

2 stu salem india 2 stu salem india

3 mia bangalore india 3 mia bangalore india

Unión a la izquierda

SELECT * FROM table1 LEFT JOIN table2 ON (table1.id = table2.id);

1 wqe chennai india 1 wqe chennai india

2 stu salem india 2 stu salem india

3 mia bangalore india 3 mia bangalore india

4 años Nueva York EE. UU. NULL NULL NULL NULL

Semi unión izquierda

SELECT * FROM table1 LEFT SEMI JOIN table2 ON (table1.id = table2.id);

1 wqe chennai india

2 stu salem india

3 mia bangalore india

nota: solo se muestran los registros de la tabla de la izquierda, mientras que para la unión izquierda se muestran ambos registros de la tabla

Kumar
fuente