CodeGym /Corsi /SQL SELF /Condizioni aggiuntive in JOIN: ON .....

Condizioni aggiuntive in JOIN: ON ... AND ...

SQL SELF
Livello 12 , Lezione 2
Disponibile

Ormai sai già come unire le tabelle usando JOIN. Ma nella vita reale la semplice corrispondenza delle chiavi spesso non basta. Spesso ti serve unire i dati solo se rispettano un criterio aggiuntivo — tipo solo i record attivi, solo i dati dell’anno corrente o solo gli ordini completati.

Ed è qui che entra in gioco l’estensione della clausola ON con AND.

Le condizioni aggiuntive in JOIN ... ON ti permettono di controllare esattamente quali righe partecipano al join, ancora prima che SQL inizi a costruire il risultato. Questo rende la query:

  • Più veloce (meno righe passano attraverso il JOIN),
  • Più precisa (il filtraggio avviene già nella fase di join),
  • Più prevedibile quando usi LEFT JOIN (diverso dal filtraggio in WHERE).

Esempio: Solo iscrizioni attive ai corsi

Supponiamo che la tabella enrollments abbia lo stato di partecipazione dello studente: active, dropped, pending.

Tabella students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Aggiorniamo la tabella enrollments:

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

Tabella courses:

id name
101 Mathematics
102 Physics
103 Computer Science

Ora vogliamo ottenere solo gli studenti che hanno corsi attivi:

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;

Risultato:

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

Qui abbiamo aggiunto AND enrollments.status = 'active' dentro ON, così il join avviene solo sui record attivi, invece di filtrare dopo l’unione.

Perché non WHERE?

Potevi anche scrivere così:

...
WHERE enrollments.status = 'active'

Ma questo si comporta diversamente con LEFT JOIN. Il filtraggio in WHERE elimina le righe senza corrispondenza (NULL), e così trasforma il LEFT JOIN in un INNER JOIN.

Invece la condizione AND enrollments.status = 'active' dentro ON limita subito le righe unite — decide quali righe entrano proprio nel join, non solo filtra il risultato dopo.

Questo approccio è super importante se vuoi mantenere le righe di una tabella anche se nell’altra non ci sono valori corrispondenti (cosa che succede spesso nei report e nelle analisi).

Altri esempi di utilizzo di ON ... AND ...

Tabella students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Tabella 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

Tabella courses:

id name
101 Math
102 Physics
103 CS

Esempio: solo corsi dell’anno corrente

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;

Qui uniamo solo i record che riguardano l’anno corrente.

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

Esempio: esclusione per valore

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

Escludiamo gli studenti che si sono ritirati già nella fase di join, non dopo il filtraggio.

name name
Otto Song Math
Otto Song CS
Alex Lin Math

Quando la condizione è dentro ON, PostgreSQL può ottimizzare il piano di join e lavorare su meno righe. Questo è super importante con tanti dati. Il filtraggio interno è più efficiente che "scartare" dopo il JOIN.

JOIN ON — non solo chiavi

Tanti pensano che ON sia solo id = id. In realtà puoi metterci dentro:

  • Operatori logici: AND, OR, NOT
  • Confronti: >, <, <>, BETWEEN, IN
  • Espressioni: EXTRACT, DATE_TRUNC, COALESCE, NULLIF

Mettiamo tutto insieme

Tabella students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Tabella faculties:

id name
10 Engineering
20 Natural Sciences
30 ← senza nome (NULL)

Tabella 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

Tabella 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;

Qui filtriamo contemporaneamente per:

  • Record attivi,
  • Corsi tranne "PE",
  • Facoltà che hanno un nome.

Risultato della query:

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

Spero che questa lezione ti sia piaciuta. Userai spesso più JOIN con filtri nelle tue query. Quasi sempre :)

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