CodeGym /Cursos /SQL SELF /Condiciones adicionales en JOIN: ON ...

Condiciones adicionales en JOIN: ON ... AND ...

SQL SELF
Nivel 12 , Lección 2
Disponible

Ya sabes cómo unir tablas usando JOIN. Pero en la vida real, a veces no basta con que coincidan las claves. Muchas veces necesitas unir datos solo si cumplen un criterio extra — por ejemplo, solo los registros activos, solo datos del año actual o solo pedidos completados.

Y aquí es donde entra en juego la extensión de la cláusula ON usando AND.

Las condiciones adicionales en JOIN ... ON te permiten controlar exactamente qué filas participan en la unión, incluso antes de que SQL empiece a construir el resultado. Esto hace que la consulta sea:

  • Más rápida (menos filas pasan por el JOIN),
  • Más precisa (el filtrado ocurre en la etapa de unión),
  • Más predecible cuando usas LEFT JOIN (a diferencia del filtrado en WHERE).

Ejemplo: Solo registros activos en los cursos

Supón que la tabla enrollments tiene el estado de participación del estudiante: active, dropped, pending.

Tabla students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Actualizamos la tabla enrollments:

student_id course_id status
1 101 active
1 103 active
2 102 dropped
3 101 active

Tabla courses:

id name
101 Mathematics
102 Physics
103 Computer Science

Ahora queremos obtener solo los estudiantes que tienen cursos activos:

SELECT 
    students.name AS student_name,
    courses.name AS course_name
FROM students 
INNER JOIN enrollments 
    ON students.id = enrollments.student_id
    AND enrollments.status = 'active'
INNER JOIN courses 
    ON enrollments.course_id = courses.id;

Resultado:

student_name course_name
Otto Song Mathematics
Otto Song Computer Science
Alex Lin Mathematics

Aquí hemos añadido AND enrollments.status = 'active' dentro de ON, para que la unión ocurra solo con los registros activos, y no se filtre después de unir.

¿Por qué no WHERE?

Podrías escribirlo así:

...
WHERE enrollments.status = 'active'

Pero esto se comporta diferente con LEFT JOIN. El filtrado en WHERE elimina las filas donde no hay coincidencias (NULL), y así convierte el LEFT JOIN en un INNER JOIN.

En cambio, la condición AND enrollments.status = 'active' dentro de ON limita directamente las filas que se unen — controla qué filas entran en la unión, no solo filtra el resultado después.

Este enfoque es especialmente importante si quieres mantener filas de una tabla aunque en la otra no haya valores coincidentes (algo muy común en informes y analítica).

Más ejemplos de uso de ON ... AND ...

Tabla students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Tabla enrollments:

student_id course_id status enrolled_at
1 101 active 2025-02-01
1 103 active 2025-03-05
2 102 dropped 2024-05-15
3 101 active 2025-03-12

Tabla courses:

id name
101 Math
102 Physics
103 CS

Ejemplo: solo cursos del año actual

SELECT
    students.name,
    courses.name,
    enrollments.enrolled_at
FROM students
JOIN enrollments
    ON students.id = enrollments.student_id
    AND EXTRACT(YEAR FROM enrollments.enrolled_at) = EXTRACT(YEAR FROM CURRENT_DATE)
JOIN courses
    ON enrollments.course_id = courses.id;

Aquí solo unimos los registros que pertenecen al año actual.

name name enrolled_at
Otto Song Math 2025-02-01
Otto Song CS 2025-03-05
Alex Lin Math 2025-03-12

Ejemplo: exclusión por valor

JOIN enrollments
    ON students.id = enrollments.student_id
    AND enrollments.status != 'dropped'

Excluimos a los estudiantes que se dieron de baja en la etapa de unión, no después de unir.

name name
Otto Song Math
Otto Song CS
Alex Lin Math

Cuando la condición está dentro de ON, PostgreSQL puede optimizar el plan de unión y procesar menos filas. Esto es súper importante cuando tienes muchos datos. El filtrado interno es más eficiente que filtrar después del JOIN.

JOIN ONno es solo para claves

Mucha gente piensa que ON es solo id = id. Pero en realidad puedes poner ahí:

  • Operadores lógicos: AND, OR, NOT
  • Comparaciones: >, <, <>, BETWEEN, IN
  • Expresiones: EXTRACT, DATE_TRUNC, COALESCE, NULLIF

Combinando todo junto

Tabla students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Tabla faculties:

id name
10 Engineering
20 Natural Sciences
30 ← sin nombre (NULL)

Tabla courses:

id name teacher faculty_id
101 Math Liam Park 10
102 Physics Chloe Zhang 20
103 CS Noah Kim 10
104 PE Ava Chen 30

Tabla enrollments:

student_id course_id status
1 101 active
1 103 active
2 102 dropped
3 101 active
3 104 active
SELECT
    s.name AS student_name,
    c.name AS course_name,
    f.name AS faculty_name
FROM students s
JOIN enrollments e
    ON s.id = e.student_id
    AND e.status = 'active'
JOIN courses c
    ON e.course_id = c.id
    AND c.name != 'PE'
JOIN faculties f
    ON c.faculty_id = f.id
    AND f.name IS NOT NULL;

Aquí filtramos a la vez por:

  • Registros activos,
  • Cursos que no sean "PE",
  • Facultades que tengan nombre.

Resultado de la consulta:

student_name course_name faculty_name
Otto Song Math Engineering
Otto Song CS Engineering
Alex Lin Math Engineering

Espero que te haya molado esta lección. Vas a usar un montón de JOINs con filtros en tus consultas. ¡Casi siempre! :)

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION