Uniendo tablas: Introducción a JOINs
En bases de datos relacionales, la información se distribuye en múltiples tablas. Los JOIN te permiten combinar datos de varias tablas en una sola consulta.
Pero, ¿por qué separar los datos en varias tablas en lugar de tenerlo todo en una sola? Imagina que repites “Rockstar Games” y “Estados Unidos” en cada juego de ese estudio. Si el nombre cambia, tendrías que actualizarlo en decenas de filas. Esto se llama normalización: dividir la información para evitar datos duplicados y mantener la consistencia. Cada tabla almacena una entidad (juegos, desarrolladores…) y se conectan entre sí mediante claves, como developer_id. Así, el nombre del estudio vive en un solo lugar y cualquier cambio se refleja automáticamente en todas las consultas.
INNER JOIN
El INNER JOIN devuelve solo las filas que tienen coincidencias en ambas tablas. Visualmente, es la intersección entre las dos tablas:
Donde A es la tabla principal (FROM) y B la tabla que unes (JOIN). Solo se devuelven las filas donde ambas tablas coinciden en la condición de unión.
SELECT columnas
FROM tabla1
INNER JOIN tabla2 ON tabla1.columna = tabla2.columna;La cláusula ON define la condición de unión, es decir, qué columnas relacionan ambas tablas.
Nuestras tablas
Ahora trabajaremos con dos tablas: videogames y developers. Los videojuegos están relacionados con sus desarrolladores a través del campo developer_id.
| id | name | country | founded_year |
|---|---|---|---|
| 1 | Nintendo | Japón | 1889 |
| 2 | Square Enix | Japón | 1975 |
| 3 | CD Projekt Red | Polonia | 1994 |
| 4 | Mojang Studios | Suecia | 2009 |
| 5 | Rockstar Games | Estados Unidos | 1998 |
| 6 | FromSoftware | Japón | 1986 |
| 7 | Valve | Estados Unidos | 1996 |
| 8 | Naughty Dog | Estados Unidos | 1984 |
| 9 | Bungie | Estados Unidos | 1991 |
| 10 | Santa Monica Studio | Estados Unidos | 1999 |
| id | title | developer_id | year | playtime_hours |
|---|---|---|---|---|
| 1 | The Legend of Zelda | 1 | 1986 | 20 |
| 2 | Super Mario Bros. | 1 | 1985 | 10 |
| 3 | Final Fantasy VII | 2 | 1997 | 40 |
| 4 | The Witcher 3 | 3 | 2015 | 100 |
| 5 | Minecraft | 4 | 2011 | 9999 |
| 6 | Grand Theft Auto V | 5 | 2013 | 80 |
| 7 | Dark Souls | 6 | 2011 | 60 |
| 8 | Portal 2 | 7 | 2011 | 8 |
| 9 | Red Dead Redemption 2 | 5 | 2018 | 70 |
| 10 | The Last of Us | 8 | 2013 | 15 |
| 11 | Halo: Combat Evolved | 9 | 2001 | 10 |
| 12 | God of War | 10 | 2018 | 25 |
Ejemplo de INNER JOIN
Para ver el título de cada juego junto al nombre de su desarrollador:
SELECT videogames.title, developers.name
FROM videogames
INNER JOIN developers ON videogames.developer_id = developers.id;Visualmente, lo que ocurre es que cada fila de videogames busca su coincidencia en developers a través de developer_id, y el resultado combina las columnas de ambas tablas:
Fíjate cómo Nintendo aparece dos veces en el resultado (porque tiene dos juegos) y Rockstar también. Cada fila del resultado es una combinación única de juego + desarrollador.
Aliases de tabla
Escribir el nombre completo de cada tabla una y otra vez resulta tedioso. En la práctica, se usan aliases (abreviaturas) para las tablas. Basta con colocar una letra o nombre corto después del nombre de la tabla:
SELECT v.title, d.name
FROM videogames v
INNER JOIN developers d ON v.developer_id = d.id;Aquí v es el alias de videogames y d el de developers. El resultado es exactamente el mismo, pero la consulta es mucho más limpia y fácil de leer. Esta es la convención que se usa en el mundo real y la que verás en la mayoría de proyectos profesionales.
Self JOIN: unir una tabla consigo misma
Un self join es un JOIN donde una tabla se une consigo misma. Se necesitan aliases obligatoriamente para distinguir las dos “copias” de la tabla.
¿Cuándo es útil? Cuando quieres comparar filas de la misma tabla entre sí. Por ejemplo, encontrar pares de juegos del mismo desarrollador:
SELECT v1.title AS juego_1, v2.title AS juego_2, v1.developer_id
FROM videogames v1
INNER JOIN videogames v2
ON v1.developer_id = v2.developer_id
AND v1.id < v2.id;La condición v1.id < v2.id evita duplicados: sin ella, obtendríamos tanto (Zelda, Mario) como (Mario, Zelda), y también cada juego emparejado consigo mismo.
CROSS JOIN: producto cartesiano
Un CROSS JOIN combina cada fila de una tabla con todas las filas de la otra. No necesita condición ON:
SELECT v.title, d.name
FROM videogames v
CROSS JOIN developers d;Si videogames tiene 12 filas y developers tiene 10, el resultado tendrá 120 filas (12 × 10). Es el producto cartesiano de ambas tablas.
En la práctica se usa poco, pero es útil para generar combinaciones, como crear un calendario cruzando años con meses, o generar todas las combinaciones posibles de dos conjuntos de datos.