Ahora toca hablar de la vida. De esa parte que no se puede evitar: los errores. Cazarlos, corregirlos y entenderlos es parte obligatoria del trabajo con datos. Vamos a ver con qué piedras te puedes tropezar usando JOIN en SQL y cómo esquivarlas.
Error 1: Olvidar la condición de unión — creación de producto cartesiano
El error más común es olvidarse de poner la condición de unión usando ON. En este caso, se genera un producto cartesiano, donde cada fila de la primera tabla se une con cada fila de la segunda. El resultado: un montón de filas que no tienen ningún sentido y solo te van a liar.
Vamos con un ejemplo. Supón que tenemos estas tablas:
Estudiantes (students):
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
Cursos (courses):
| course_id | course_name |
|---|---|
| 101 | Matemáticas |
| 102 | Historia |
Ahora escribimos una consulta olvidando el ON:
SELECT *
FROM students
JOIN courses;
Resultado:
| student_id | name | course_id | course_name |
|---|---|---|---|
| 1 | Otto | 101 | Matemáticas |
| 1 | Otto | 102 | Historia |
| 2 | Anna | 101 | Matemáticas |
| 2 | Anna | 102 | Historia |
No parece correcto, ¿verdad? Esta pesadilla se llama producto cartesiano.
Cómo arreglarlo: usa ON para indicar cómo se relacionan los datos entre las tablas.
SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;
Y aquí aparece un nuevo capítulo de errores...
Protección contra despistes
Este problema es tan común que en PostgreSQL prohibieron usar JOIN sin ON y condición.
Si de verdad necesitas unir cada fila con cada una, puedes usar la sintaxis sin JOIN:
SELECT *
FROM students, courses;
Otra opción, la tercera opción - cuando JOIN sin ON sí funciona:
- Con
NATURAL JOIN— selecciona automáticamente las columnas con el mismo nombre. - Con
USING— indicas la lista de columnas por las que se unen las tablas. CROSS JOIN— siempre sin condición, igual que el producto cartesiano.
Error 2: Condición de unión incorrecta
A veces pones la condición de unión, pero la pones mal. Por ejemplo, unes tablas por campos que no tienen nada que ver.
Supón que quieres obtener la lista de estudiantes y los cursos en los que están inscritos, pero te equivocas y unes las tablas por campos que no están relacionados:
SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;
Esta consulta dará un resultado incorrecto, porque student_id y course_id no tienen nada que ver.
Cómo arreglarlo: asegúrate de usar las columnas correctas para unir. Una unión correcta podría ser así (si tienes una tabla enrollments que relaciona estudiantes y cursos):
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Error 3: Duplicación de filas en el resultado
Cuando añades varios JOIN en una consulta, a veces eso genera filas duplicadas. Esto pasa si en las tablas de JOIN hay registros repetidos, o si pusiste mal las condiciones de unión.
Por ejemplo, el estudiante Otto está inscrito dos veces en el mismo curso en la tabla enrollments.
Registros en enrollments:
| student_id | course_id |
|---|---|
| 1 | 101 |
| 1 | 101 |
Ahora la consulta con JOIN da este resultado:
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Resultado:
| name | course_name |
|---|---|
| Otto | Matemáticas |
| Otto | Matemáticas |
Cómo arreglarlo: primero, asegúrate de que no tienes datos duplicados en tus tablas. Segundo, si es el comportamiento esperado, elimina duplicados usando DISTINCT:
SELECT DISTINCT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Error 4: Pérdida de filas usando INNER JOIN
INNER JOIN solo devuelve las filas que coinciden en ambas tablas. Si en una tabla no hay valor correspondiente, la fila se descarta. Puedes perder datos si eliges mal el tipo de unión.
Por ejemplo, tenemos un estudiante que aún no está inscrito en ningún curso:
Estudiantes (students):
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
| 3 | Dhany |
Inscripciones (enrollments):
| student_id | course_id |
|---|---|
| 1 | 101 |
| 2 | 102 |
Ahora la consulta con INNER JOIN:
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Resultado:
| name | course_name |
|---|---|
| Otto | Matemáticas |
| Anna | Historia |
¿Y dónde está Dhany? Si quieres incluir estudiantes sin cursos, tienes que usar LEFT JOIN:
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id;
Error 5: Manejo incorrecto de valores NULL
Si en una de las tablas hay filas con valores vacíos (NULL), pueden quedarse fuera del resultado (por ejemplo, al usar condiciones de filtrado).
Ejemplo: usas LEFT JOIN, pero luego añades un WHERE para filtrar.
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name = 'Matemáticas';
Ahora los estudiantes sin cursos no aparecerán en el resultado, aunque hayas usado LEFT JOIN.
Cómo arreglarlo: si quieres incluir filas sin cursos, cambia el WHERE por ON o añade una condición extra:
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name IS NULL OR courses.course_name = 'Matemáticas';
Error 6: Confusión entre tipos de unión
Te lías con qué tipo de unión usar. Por ejemplo, usas RIGHT JOIN cuando podrías usar LEFT JOIN cambiando el orden de las tablas.
Cómo evitar la confusión:
- Usa
LEFT JOINsiempre que puedas. Es más intuitivo. - Cambia el orden de las tablas para no tener que usar
RIGHT JOIN.
GO TO FULL VERSION