INNER, LEFT, RIGHT, FULL, CROSS, self-join y anti-join.
0 / 8 retos resueltos📘 Clases 9 y 11 · INNER / LEFT / RIGHT / FULL JOIN y alias
Al terminar esta práctica podrás…
Unir dos o más tablas por sus claves con INNER JOIN … ON y alias.
Conservar filas sin pareja con LEFT JOIN y detectar «huérfanos» (anti-join).
Relacionar una tabla consigo misma (self-join) para jerarquías jefe → empleado.
Combinar JOIN con WHERE, GROUP BY y HAVING en informes.
Un modelo normalizado reparte la información en varias tablas. El JOIN las vuelve a combinar
siguiendo las claves: normalmente la FK de una tabla con la PK de otra
(employees.department_id = departments.department_id).
INNER JOIN (o solo JOIN): solo las filas que tienen pareja en ambas tablas.
LEFT JOIN: todas las filas de la tabla izquierda; si no hay pareja, las columnas de la derecha quedan en NULL.
RIGHT JOIN: lo mismo, conservando la tabla derecha. FULL JOIN: conserva ambas.
CROSS JOIN: todas las combinaciones posibles (producto cartesiano).
Usa alias cortos (e, d, l) y antepónlos a las columnas: evita la
ambigüedad cuando dos tablas tienen columnas con el mismo nombre.
Sintaxis
SELECT e.col, d.col
FROM tabla1 e
[INNER | LEFT | RIGHT | FULL] JOIN tabla2 d
ON e.fk = d.pk
WHERE …;
INNER JOIN
Intersección: solo filas con coincidencia.
LEFT JOIN
Todo lo de la izquierda + lo que coincida de la derecha.
Anti-join
LEFT JOIN … WHERE derecha.pk IS NULL: filas sin pareja.
Self-join
La misma tabla dos veces con alias distintos (empleado / jefe).
FROM a, b WHERE a.x = b.x: sintaxis antigua, mejor evitarla.
SQLite 3.39+
Soporta INNER, LEFT, RIGHT, FULL y CROSS JOIN
MySQL
Sin FULL JOIN: se emula con LEFT … UNION … RIGHT
Oracle
Todos los JOIN ANSI; sintaxis antigua (+) para outer join
1 · Ejemplos guiados · ejecuta y modifica cada bloque
01INNER JOIN con alias
Cada empleado con el nombre de su departamento (clase 11).
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
02Cuatro tablas encadenadas
Empleado → departamento → ubicación → país.
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
03LEFT JOIN: conservar las filas sin pareja
Todas las ciudades, tengan o no departamentos. Las que no tienen muestran NULL.
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
04Anti-join: ubicaciones sin departamentos
Agregando WHERE d.department_id IS NULL nos quedamos solo con las filas sin pareja (técnica de la guía de ejercicios: «proveedores sin artículos»).
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
05Self-join: empleado y su jefe
employees aparece dos veces: e (empleado) y m (jefe). Con LEFT JOIN no perdemos al presidente, que no tiene jefe.
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
06JOIN + GROUP BY + HAVING (clase 9)
Total de salarios por título de cargo, solo los que superan 100000.
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
07FULL JOIN emulado con UNION
Donde no existe FULL JOIN (MySQL), se combina un LEFT y un RIGHT (escrito como LEFT invertido) con UNION.
sql-joins.sql
Presiona «ejecutar» para ver el resultado.
⚠ Errores frecuentes
Olvidar el ON (o ponerlo mal) genera un producto cartesiano: 102 × 11 = 1122 filas.
No usar alias y escribir department_id a secas cuando existe en ambas tablas: error «ambiguous column name».
Hacer un LEFT JOIN y luego filtrar la tabla derecha en el WHERE (WHERE d.department_name = 'IT'): lo convierte en INNER. Pon esa condición en el ON.
Contar con COUNT(*) después de un LEFT JOIN: cuenta también las filas sin pareja. Usa COUNT(columna_de_la_derecha).
2 · Retos con corrección automática
Escribe tu solución y pulsa comprobar (Ctrl + Enter). Tu consulta y la solución se ejecutan
en bases limpias y se comparan los resultados: no importan los nombres de las columnas, sí los datos (y el
orden, cuando el reto lo pide). Si te atascas, usa la pista o mira el resultado esperado.
3 · Preguntas tipo solemne
1. ¿Qué JOIN devuelve todos los estudiantes, aunque no estén inscritos en ningún curso (clase 11)?
LEFT JOIN conserva todas las filas de la tabla izquierda; si no hay pareja, la derecha queda en NULL.
2. ¿Qué devuelve esta consulta?
SELECT p.nombre
FROM proveedor p
LEFT JOIN articulo a ON p.id = a.proveedor_id
WHERE a.id IS NULL;
Es un anti-join: el LEFT JOIN deja en NULL a los proveedores sin artículos, y el WHERE se queda solo con ellos.
3. En una relación 1:N clientes–pedidos, un cliente con 3 pedidos aparece en un INNER JOIN…
El lado «uno» se repite por cada coincidencia en el lado «muchos».
4. ¿Qué tipo de JOIN conviene para listar cada empleado junto a su jefe en la misma tabla?
La tabla se une consigo misma con alias distintos: e.manager_id = m.employee_id.