Esta es una pregunta muy común, por lo que esta respuesta se basa en este artículo que escribí.
Relación de mesa
Teniendo en cuenta que tenemos lo siguiente post
y las post_comment
tablas:
El post
tiene los siguientes registros:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
y post_comment
tiene las siguientes tres filas:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
SQL INNER JOIN
La cláusula SQL JOIN le permite asociar filas que pertenecen a diferentes tablas. Por ejemplo, CROSS JOIN creará un producto cartesiano que contiene todas las combinaciones posibles de filas entre las dos tablas de unión.
Si bien CROSS JOIN es útil en ciertos escenarios, la mayoría de las veces, desea unir tablas en función de una condición específica. Y ahí es donde entra en juego INNER JOIN.
SQL INNER JOIN nos permite filtrar el producto cartesiano de unir dos tablas en función de una condición que se especifica mediante la cláusula ON.
SQL INNER JOIN - CONdición "siempre verdadera"
Si proporciona una condición "siempre verdadera", INNER JOIN no filtrará los registros unidos, y el conjunto de resultados contendrá el Producto cartesiano de las dos tablas de unión.
Por ejemplo, si ejecutamos la siguiente consulta SQL INNER JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
Obtendremos todas las combinaciones post
y post_comment
registros:
| p.id | pc.id |
|---------|------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
Por lo tanto, si la condición de la cláusula ON es "siempre verdadera", INNER JOIN es simplemente equivalente a una consulta CROSS JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SQL INNER JOIN - CONdición "siempre falsa"
Por otro lado, si la condición de la cláusula ON es "siempre falsa", todos los registros unidos se filtrarán y el conjunto de resultados estará vacío.
Entonces, si ejecutamos la siguiente consulta SQL INNER JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
No obtendremos ningún resultado:
| p.id | pc.id |
|---------|------------|
Esto se debe a que la consulta anterior es equivalente a la siguiente consulta CROSS JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SQL INNER JOIN - cláusula ON utilizando las columnas Clave externa y Clave primaria
La condición de cláusula ON más común es la que coincide con la columna Clave externa en la tabla secundaria con la columna Clave primaria en la tabla primaria, como se ilustra en la siguiente consulta:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id
Al ejecutar la consulta SQL INNER JOIN anterior, obtenemos el siguiente conjunto de resultados:
| p.id | pc.post_id | pc.id | p.title | pc.review |
|---------|------------|------------|------------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
Por lo tanto, solo los registros que coinciden con la condición de la cláusula ON se incluyen en el conjunto de resultados de la consulta. En nuestro caso, el conjunto de resultados contiene todo post
junto con sus post_comment
registros. Las post
filas que no tienen asociadas post_comment
se excluyen ya que no pueden cumplir la condición de la cláusula ON.
Nuevamente, la consulta SQL INNER JOIN anterior es equivalente a la siguiente consulta CROSS JOIN:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
Las filas no tachadas son las que satisfacen la cláusula WHERE, y solo estos registros se incluirán en el conjunto de resultados. Esa es la mejor manera de visualizar cómo funciona la cláusula INNER JOIN.
El | p.id | pc.post_id | pc.id | p.title | pc.review |
| ------ | ------------ | ------- | ----------- | --------- - |
El | 1 | 1 | 1 | Java | Bueno |
El | 1 | 1 | 2 | Java | Excelente |
El | 1 | 2 | 3 | Java | Impresionante |
El | 2 | 1 | 1 | Hibernar | Bueno |
El | 2 | 1 | 2 | Hibernar | Excelente |
El | 2 | 2 | 3 | Hibernar | Impresionante |
El | 3 | 1 | 1 | JPA | Bueno |
El | 3 | 1 | 2 | JPA | Excelente |
El | 3 | 2 | 3 | JPA | Impresionante |
Conclusión
Una declaración INNER JOIN puede reescribirse como CROSS JOIN con una cláusula WHERE que coincida con la misma condición que usó en la cláusula ON de la consulta INNER JOIN.
No es que esto solo se aplique a INNER JOIN, no a OUTER JOIN.