Aprende SQL

Uniendo tablas: Introducción a JOINs

Lección 01 · Uniones y valores nulos

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:

INNER JOIN
Solo coincidencias
LEFT JOIN
Todo de A + coincidencias de B
RIGHT JOIN
Todo de B + coincidencias de A
FULL OUTER JOIN
Todo de ambas 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.

Nombre de la Tabla: developers

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

Nombre de la Tabla: videogames

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:

videogames developers Resultado
title developer_id id name title name
Zelda 1 1 Nintendo Zelda Nintendo
Mario 1 5 Rockstar Mario Nintendo
GTA V 5 7 Valve GTA V Rockstar
Portal 2 7 Portal 2 Valve
RDR 2 5 RDR 2 Rockstar

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.

Tablas de esta lección

developers4 cols

Estructura

🔑idINTEGERnameTEXTcountryTEXTfounded_yearINTEGER

Datos de ejemplo (5 filas)

idnamecountryfounded_year
1NintendoJapón1889
2Square EnixJapón1975
3CD Projekt RedPolonia1994
4Mojang StudiosSuecia2009
5Rockstar GamesEstados Unidos1998
6FromSoftwareJapón1986
7ValveEstados Unidos1996
8Naughty DogEstados Unidos1984
9BungieEstados Unidos1991
10Santa Monica StudioEstados Unidos1999
videogames5 cols

Estructura

🔑idINTEGERtitleTEXTdeveloper_idINTEGERyearINTEGERplaytime_hoursINTEGER

Datos de ejemplo (5 filas)

idtitledeveloper_idyearplaytime_hours
1The Legend of Zelda1198620
2Super Mario Bros.1198510
3Final Fantasy VII2199740
4The Witcher 332015100
5Minecraft420119999
6Grand Theft Auto V5201380
7Dark Souls6201160
8Portal 2720118
9Red Dead Redemption 25201870
10The Last of Us8201315
11Halo: Combat Evolved9200110
12God of War10201825

Ejercicios

Muestra el título de cada videojuego junto al nombre de su desarrollador.

sql

Muestra el título y el nombre del desarrollador usando alias de tabla (v y d).

sql

Encuentra pares de videojuegos del mismo desarrollador (juego_1, juego_2, developer_id) evitando duplicados.

sql