Respuestas:
SQL JOIN
?SQL JOIN
es un método para recuperar datos de dos o más tablas de bases de datos.
SQL JOIN
s?Hay un total de cinco JOIN
s. Son :
1. JOIN or INNER JOIN
2. OUTER JOIN
2.1 LEFT OUTER JOIN or LEFT JOIN
2.2 RIGHT OUTER JOIN or RIGHT JOIN
2.3 FULL OUTER JOIN or FULL JOIN
3. NATURAL JOIN
4. CROSS JOIN
5. SELF JOIN
En este tipo de a JOIN
, obtenemos todos los registros que coinciden con la condición en ambas tablas, y los registros en ambas tablas que no coinciden no se informan.
En otras palabras, INNER JOIN
se basa en el hecho único de que: SOLO las entradas coincidentes en AMBAS tablas DEBEN aparecer en la lista.
Tenga en cuenta que una JOIN
sin otras JOIN
palabras clave (como INNER
, OUTER
, LEFT
, etc) es una INNER JOIN
. En otras palabras, JOIN
es un azúcar sintáctico para INNER JOIN
(ver: Diferencia entre JOIN y INNER JOIN ).
OUTER JOIN
recupera
O bien, las filas coincidentes de una tabla y todas las filas de la otra tabla O, todas las filas de todas las tablas (no importa si hay una coincidencia).
Hay tres tipos de unión externa:
2.1 IZQUIERDA EXTERIOR O IZQUIERDA
Esta unión devuelve todas las filas de la tabla izquierda junto con las filas coincidentes de la tabla derecha. Si no hay columnas que coincidan en la tabla de la derecha, devuelve NULL
valores.
2.2 UNIÓN EXTERIOR DERECHA o UNIÓN DERECHA
Esto JOIN
devuelve todas las filas de la tabla derecha junto con las filas coincidentes de la tabla izquierda. Si no hay columnas que coincidan en la tabla izquierda, devuelve NULL
valores.
2.3 FULL OUTER JOIN o FULL JOIN
Esto JOIN
combina LEFT OUTER JOIN
y RIGHT OUTER JOIN
. Devuelve filas de cualquier tabla cuando se cumplen las condiciones y devuelve NULL
valor cuando no hay coincidencia.
En otras palabras, OUTER JOIN
se basa en el hecho de que: SOLO las entradas coincidentes en UNA de las tablas (DERECHA o IZQUIERDA) o AMBAS de las tablas (COMPLETO) DEBEN aparecer en la lista.
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
Se basa en las dos condiciones:
JOIN
se hace en todas las columnas con el mismo nombre de la igualdad.Esto parece ser más de naturaleza teórica y como resultado (probablemente) la mayoría de los DBMS ni siquiera se molestan en apoyar esto.
Es el producto cartesiano de las dos tablas involucradas. El resultado de un CROSS JOIN
testamento no tiene sentido en la mayoría de las situaciones. Además, no necesitaremos esto en absoluto (o necesita lo menos, para ser precisos).
No es una forma diferente de JOIN
, más bien es una JOIN
( INNER
, OUTER
, etc.) de una tabla consigo misma.
Dependiendo del operador utilizado para una JOIN
cláusula, puede haber dos tipos de JOIN
s. Son
Para cualquier JOIN
tipo ( INNER
, OUTER
, etc.), si usamos sólo el operador de igualdad (=), entonces se dice que el JOIN
es una EQUI JOIN
.
Esto es igual EQUI JOIN
pero permite a todos los demás operadores como>, <,> = etc.
Muchos consideran ambos
EQUI JOIN
y ThetaJOIN
similares aINNER
,OUTER
etc.JOIN
s. Pero creo firmemente que es un error y hace que las ideas sean vagas. PorqueINNER JOIN
,OUTER JOIN
etc están todos conectados con las tablas y sus datos, mientras queEQUI JOIN
yTHETA JOIN
solamente están conectados con los operadores que utilizamos en el primero.Nuevamente, hay muchos que consideran
NATURAL JOIN
como una especie de "peculiar"EQUI JOIN
. De hecho, es cierto, debido a la primera condición que mencionéNATURAL JOIN
. Sin embargo, no tenemos que restringir eso simplemente aNATURAL JOIN
s solo.INNER JOIN
s, s,OUTER JOIN
etc., podría ser unEQUI JOIN
también.
Definición:
JOINS es una forma de consultar los datos que se combinaron de varias tablas simultáneamente.
En cuanto a RDBMS, hay 5 tipos de combinaciones:
Equi-Join: combina registros comunes de dos tablas según la condición de igualdad. Técnicamente, la unión se realiza utilizando el operador de igualdad (=) para comparar los valores de la clave primaria de una tabla y los valores de la clave externa de otra tabla, por lo tanto, el conjunto de resultados incluye registros comunes (coincidentes) de ambas tablas. Para la implementación, vea INNER-JOIN.
Natural-Join: es una versión mejorada de Equi-Join, en la que la operación SELECT omite la columna duplicada. Para implementación ver INNER-JOIN
No-Equi-Join: es inverso a Equi-join donde la condición de unión se utiliza con un operador distinto de igual (=) por ejemplo,! =, <=,> =,>, <O ENTRE, etc. Para la implementación, vea INNER-JOIN.
Self-Join:: Un comportamiento personalizado de join donde una tabla se combina consigo misma; Esto normalmente se necesita para consultar tablas de autorreferencia (o entidad de relación unaria). Para la implementación ver INNER-JOINs.
Producto cartesiano: combina de forma cruzada todos los registros de ambas tablas sin ninguna condición. Técnicamente, devuelve el conjunto de resultados de una consulta sin WHERE-Cláusula.
Según el avance y la preocupación de SQL, hay 3 tipos de combinaciones y todas las combinaciones RDBMS se pueden lograr utilizando estos tipos de combinaciones.
INNER-JOIN: combina (o combina) filas coincidentes de dos tablas. La coincidencia se realiza en base a columnas comunes de tablas y su operación de comparación. Si la condición se basa en la igualdad, entonces: EQUI-JOIN realizó, de lo contrario, no EQUI-Join.
OUTER-JOIN: combina (o combina) filas coincidentes de dos tablas y filas no coincidentes con valores NULL. Sin embargo, se puede personalizar la selección de filas no coincidentes, por ejemplo, seleccionando una fila no coincidente de la primera tabla o la segunda tabla por subtipos: IZQUIERDA EXTERIOR IZQUIERDA y UNIÓN EXTERIOR DERECHA.
2.1. LEFT Outer JOIN (también conocido como LEFT-JOIN): devuelve filas coincidentes de dos tablas y no coincidentes de la tabla LEFT (es decir, la primera tabla) solamente.
2.2. UNIÓN EXTERIOR DERECHA (también conocido como UNIÓN DERECHA): devuelve filas coincidentes de dos tablas y no coincidentes solo de la tabla DERECHA.
2.3. FULL OUTER JOIN (también conocido como OUTER JOIN): devuelve coincidencias y no coincidencias de ambas tablas.
CROSS-JOIN: esta unión no combina / combina sino que realiza un producto cartesiano.
Nota: Self-JOIN puede lograrse ya sea INNER-JOIN, OUTER-JOIN y CROSS-JOIN según los requisitos, pero la tabla debe unirse consigo misma.
1.1: INNER-JOIN: implementación de Equi-join
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2: INNER-JOIN: implementación de Natural-JOIN
Select A.*, B.Col1, B.Col2 --But no B.ForeignKeyColumn in Select
FROM Table1 A
INNER JOIN Table2 B On A.Pk = B.Fk;
1.3: INNER-JOIN con implementación NO-Equi-join
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4: INNER-JOIN con AUTO-JOIN
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1: UNIÓN EXTERNA (unión externa completa)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2: IZQUIERDA
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3: UNIÓN DERECHA
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1: UNIÓN CRUZADA
Select *
FROM TableA CROSS JOIN TableB;
3.2: CROSS JOIN-Self JOIN
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//O//
Select *
FROM Table1 A1,Table1 A2;
intersect
/ except
/ union
; aquí los círculos son las filas devueltas por left
& right
join
, como dicen las etiquetas numeradas. La imagen de AXB no tiene sentido. cross join
= inner join on 1=1
& es un caso especial del primer diagrama.
UNION JOIN
. Ahora queda obsoleto en SQL: 2003.
Curiosamente, la mayoría de las otras respuestas sufren de estos dos problemas:
Recientemente escribí un artículo sobre el tema: Una guía completa, probablemente incompleta, sobre las diferentes formas de unir tablas en SQL , que resumiré aquí.
Es por eso que los diagramas de Venn los explican de manera tan inexacta, porque un JOIN crea un producto cartesiano entre las dos tablas unidas. Wikipedia lo ilustra muy bien:
La sintaxis SQL para productos cartesianos es CROSS JOIN
. Por ejemplo:
SELECT *
-- This just generates all the days in January 2017
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Here, we're combining all days with all departments
CROSS JOIN departments
Que combina todas las filas de una tabla con todas las filas de la otra tabla:
Fuente:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
Resultado:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
Si solo escribimos una lista de tablas separadas por comas, obtendremos lo mismo:
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
Un INNER JOIN
es solo un filtro CROSS JOIN
donde el predicado de filtro se llama Theta
en álgebra relacional.
Por ejemplo:
SELECT *
-- Same as before
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at
Tenga en cuenta que la palabra clave INNER
es opcional (excepto en MS Access).
( mira el artículo para ver ejemplos de resultados )
Un tipo especial de Theta-JOIN es equi JOIN, que más usamos. El predicado une la clave primaria de una tabla con la clave externa de otra tabla. Si usamos la base de datos Sakila para ilustración, podemos escribir:
SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
Esto combina a todos los actores con sus películas.
O también, en algunas bases de datos:
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
La USING()
sintaxis permite especificar una columna que debe estar presente a ambos lados de las tablas de una operación JOIN y crea un predicado de igualdad en esas dos columnas.
Otras respuestas han enumerado este "tipo de UNIÓN" por separado, pero eso no tiene sentido. Es solo una forma de sintaxis de azúcar para equi JOIN, que es un caso especial de Theta-JOIN o INNER JOIN. UNIÓN NATURAL simplemente recopila todas las columnas que son comunes a ambas tablas que se unen y las une USING()
. Lo cual casi nunca es útil, debido a coincidencias accidentales (como LAST_UPDATE
columnas en la base de datos Sakila ).
Aquí está la sintaxis:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
Ahora, OUTER JOIN
es un poco diferente INNER JOIN
ya que crea UNION
varios productos cartesianos. Podemos escribir:
-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>
-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
SELECT * FROM b WHERE <predicate>
)
Nadie quiere escribir lo último, por lo que escribimos OUTER JOIN
(que generalmente está mejor optimizado por las bases de datos).
Como INNER
, la palabra clave OUTER
es opcional, aquí.
OUTER JOIN
viene en tres sabores:
LEFT [ OUTER ] JOIN
: La tabla izquierda de la JOIN
expresión se agrega a la unión como se muestra arriba.RIGHT [ OUTER ] JOIN
: La tabla derecha de la JOIN
expresión se agrega a la unión como se muestra arriba.FULL [ OUTER ] JOIN
: Ambas tablas de la JOIN
expresión se agregan a la unión como se muestra arriba.Todo esto se puede combinar con la palabra clave USING()
o con NATURAL
(en realidad, he tenido un caso de uso del mundo real para un NATURAL FULL JOIN
reciente )
Hay algunas sintaxis históricas y obsoletas en Oracle y SQL Server, que OUTER JOIN
ya eran compatibles antes de que el estándar SQL tuviera una sintaxis para esto:
-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
Dicho esto, no use esta sintaxis. Solo enumero esto aquí para que pueda reconocerlo en publicaciones antiguas de blog / código heredado.
OUTER JOIN
Pocas personas saben esto, pero el estándar SQL especifica particionado OUTER JOIN
(y Oracle lo implementa). Puedes escribir cosas como esta:
WITH
-- Using CONNECT BY to generate all dates in January
days(day) AS (
SELECT DATE '2017-01-01' + LEVEL - 1
FROM dual
CONNECT BY LEVEL <= 31
),
-- Our departments
departments(department, created_at) AS (
SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
SELECT 'Dept 5', DATE '2017-04-02' FROM dual
)
SELECT *
FROM days
LEFT JOIN departments
PARTITION BY (department) -- This is where the magic happens
ON day >= created_at
Partes del resultado:
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
El punto aquí es que todas las filas del lado particionado de la unión terminarán en el resultado independientemente de si JOIN
coinciden con algo en el "otro lado de la UNIÓN". Larga historia corta: Esto es para llenar datos escasos en los informes. ¡Muy útil!
¿Seriamente? Ninguna otra respuesta tiene esto? Por supuesto que no, porque desafortunadamente no tiene una sintaxis nativa en SQL (al igual que ANTI JOIN a continuación). Pero podemos usar IN()
y EXISTS()
, por ejemplo, para encontrar a todos los actores que han jugado en películas:
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
El WHERE a.actor_id = fa.actor_id
predicado actúa como el predicado de semiunión. Si no lo cree, consulte los planes de ejecución, por ejemplo, en Oracle. Verá que la base de datos ejecuta una operación SEMI JOIN, no el EXISTS()
predicado.
Esto es justo lo contrario de SEMI JOIN ( tener cuidado de no usar NOT IN
embargo , ya que tiene una importante advertencia)
Aquí están todos los actores sin películas:
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Algunas personas (especialmente las personas de MySQL) también escriben ANTI JOIN de esta manera:
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
Creo que la razón histórica es el rendimiento.
Dios mío, este es demasiado genial. Soy el único en mencionarlo? Aquí hay una consulta genial:
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN inventory AS i USING (film_id)
JOIN rental AS r USING (inventory_id)
JOIN payment AS p USING (rental_id)
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
ON true
Encontrará el TOP 5 de películas productoras de ingresos por actor. Cada vez que necesite una consulta TOP-N-per-something, LATERAL JOIN
será su amigo. Si eres una persona de SQL Server, entonces conoces este JOIN
tipo bajo el nombreAPPLY
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
OK, tal vez eso es hacer trampa, porque una expresión LATERAL JOIN
o APPLY
es realmente una "subconsulta correlacionada" que produce varias filas. Pero si permitimos "subconsultas correlacionadas", también podemos hablar de ...
Oracle e Informix solo lo implementan realmente (que yo sepa), pero se puede emular en PostgreSQL usando matrices y / o XML y en SQL Server usando XML.
MULTISET
produce una subconsulta correlacionada y anida el conjunto resultante de filas en la consulta externa. La consulta a continuación selecciona todos los actores y para cada actor recopila sus películas en una colección anidada:
SELECT a.*, MULTISET (
SELECT f.*
FROM film AS f
JOIN film_actor AS fa USING (film_id)
WHERE a.actor_id = fa.actor_id
) AS films
FROM actor
Como se ha visto, hay más tipos de JOIN que sólo el "aburrido" INNER
, OUTER
y CROSS JOIN
que por lo general se mencionan. Más detalles en mi artículo . Y, por favor, deje de usar los diagramas de Venn para ilustrarlos.
Voy a presionar a mi mascota: la palabra clave USING.
Si ambas tablas en ambos lados de JOIN tienen sus claves foráneas correctamente nombradas (es decir, el mismo nombre, no solo "id"), esto se puede usar:
SELECT ...
FROM customers JOIN orders USING (customer_id)
Esto me parece muy práctico, legible y no se usa con la frecuencia suficiente.