CodeGym /Corsi /SQL SELF /Controllo dell'esistenza dei dati con EXISTS e NOT EXIS...

Controllo dell'esistenza dei dati con EXISTS e NOT EXISTS

SQL SELF
Livello 13, Lezione 3
Disponibile

Benvenuto in una nuova lezione su SQL! Oggi ci conosciamo con gli operatori più invisibili ma incredibilmente potenti — EXISTS e NOT EXISTS. Immagina uno 007 che non lascia tracce, ma ti dice subito: "Sì, l'oggetto esiste" oppure "No, qui è vuoto". Questi operatori non restituiscono dati direttamente, ma ti permettono di fare controlli logici precisi nelle query.

Partiamo dalle basi. EXISTS — è un operatore che controlla l'esistenza delle righe nel risultato di una subquery. Se la subquery restituisce almeno una riga, la condizione EXISTS restituisce TRUE, altrimenti — FALSE.

SELECT 1
WHERE EXISTS (
    SELECT * 
    FROM students 
    WHERE grade > 3.5
);

Come vedi, non ci interessano i dati stessi della subquery, ma solo il fatto che esistano tali righe. Se almeno una riga soddisfa la condizione, la query restituisce 1.

Sintassi di EXISTS

La sintassi di EXISTS è semplice:

SELECT colonne
FROM tabella
WHERE EXISTS (
    SELECT 1
    FROM altra_tabella
    WHERE condizione
);

Spiegazione:

  • La subquery dentro EXISTS può essere qualsiasi query.
  • È proprio il risultato della subquery che decide se torna TRUE o FALSE.

Esempio: Ci sono studenti con voto sopra 4?

Immaginiamo la tabella students:

id name grade
1 Otto 3.2
2 Anna 4.7
3 Dan 5.0
4 Lina 2.9

Supponiamo di voler controllare se esistono studenti con voto sopra 4. Usiamo questa query:

SELECT 'Ci sono studenti con voto alto!'
WHERE EXISTS (
    SELECT 1
    FROM students
    WHERE grade > 4
);

Risultato:

Ci sono studenti con voto alto!

Perché EXISTS è più veloce di IN?

Il vantaggio principale di EXISTS è che ferma l'esecuzione della subquery appena trova la prima corrispondenza. Questo significa che se hai una condizione che controlla l'esistenza dei dati, EXISTS può essere super efficiente.

Per esempio, immagina che nella tabella students ci siano milioni di righe, ma cerchiamo solo una corrispondenza (grade > 4). Appena SQL trova la prima riga che va bene, la query si ferma.

Uso di NOT EXISTS

Ora parliamo di NOT EXISTS. Questo operatore funziona come l'opposto di EXISTS. Restituisce TRUE se la subquery non restituisce nessuna riga.

Esempio: trovare studenti senza voti (NULL)

Supponiamo che nella nostra tabella ci siano studenti che ancora non hanno un voto:

id name grade
1 Otto NULL
2 Anna 4.7
3 Dan 5.0
4 Lina NULL

Vogliamo selezionare tutti gli studenti senza voto. Usiamo NOT EXISTS:

SELECT *
FROM students s
WHERE NOT EXISTS (
    SELECT 1
    FROM students 
    WHERE grade IS NOT NULL
    AND id = s.id
);

Risultato:

id name grade
1 Otto NULL
4 Lina NULL

Confronto tra EXISTS e IN

A volte sembra che EXISTS e IN facciano la stessa cosa. A prima vista sì, ma ci sono delle sfumature. Soprattutto se da qualche parte c'è un NULL. Allora il comportamento di IN può diventare strano, mentre EXISTS ti salva.

Dai, vediamo con un esempio.

Tabella courses (corsi che puoi seguire):

course_id name
1 Matematica
2 Storia

Ecco gli studenti:

student_id name
1 Alex Lin
2 Anna Song
3 Maria Chi
4 Dan Seth
5 Shadow Moon

Tabella enrollments (chi si è iscritto a quale corso):

student_id course_id
1 1
2 2
3 NULL

Vogliamo selezionare i nomi dei corsi dove qualcuno si è iscritto. Sembra facile.

Usando IN:

SELECT name
FROM courses
WHERE course_id IN (
    SELECT course_id 
    FROM enrollments
);

A prima vista dovrebbe funzionare. Ma se in enrollments c'è NULL in courseid, come per Maria Chi, IN può restituire... niente! Perché NULL rende la subquery "indefinita", e SQL si confonde: magari NULL è proprio quel courseid che cerchiamo?

Usando EXISTS:

SELECT name
FROM courses c
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE c.course_id = e.course_id
);

Invece EXISTS controlla: "C'è almeno una riga dove course_id coincide?" — e basta. Non si preoccupa se c'è un NULL da qualche parte, perché cerca solo corrispondenze concrete, non una lista di valori.

Morale: se nella subquery può esserci NULL, meglio usare EXISTS per non avere sorprese.

Esempi di casi reali

Tabella students:

id name
1 Alex Lin
2 Anna Song
3 Maria Chi
4 Dan Seth
5 Shadow Moon

Tabella enrollments:

student_id course_id
1 1
2 2
3 NULL

Esempio 1. Studenti iscritti ai corsi

Troviamo chi si è già iscritto a qualche corso (anche in modo strano, come Maria Chi):

SELECT name
FROM students s
WHERE EXISTS (
    SELECT 1
    FROM enrollments e
    WHERE s.id = e.student_id
);

Risultato:

Alex Lin
Anna Song
Maria Chi

Se uno studente appare in enrollments — viene selezionato, anche se il suo course_id non è chiaro.

Esempio 2. Studenti senza corsi

Ora troviamo chi esiste nel sistema — ma non si è ancora iscritto a nulla:

SELECT name
FROM students s
WHERE NOT EXISTS (
    SELECT 1
    FROM enrollments e
    WHERE s.id = e.student_id
);

Risultato:

Dan Seth
Shadow Moon

Sembra che questi due non abbiano ancora trovato il corso giusto. O magari si sono dimenticati di iscriversi :)

Esempio 3. Selezione dei corsi con più di 5 studenti iscritti

Tabella courses:

course_id name
1 Matematica
2 Storia
3 Biologia
4 Filosofia

Tabella enrollments:

student_id course_id
1 1
2 1
3 1
4 1
5 1
6 1
7 2
8 2
9 2
10 NULL

Vogliamo trovare quei corsi dove si sono iscritti più di cinque studenti. Qui EXISTS chiede: "C'è almeno un gruppo di righe per questo corso dove gli studenti sono più di cinque?"

SELECT name
FROM courses c
WHERE EXISTS (
    SELECT 1
    FROM enrollments e
    WHERE c.course_id = e.course_id
    GROUP BY e.course_id
    HAVING COUNT(*) > 5
);

Risultato:

Matematica

Solo al corso "Matematica" (course_id = 1) si sono iscritti sei studenti. Gli altri corsi per ora non sono così popolari.

Errori comuni con EXISTS e NOT EXISTS

  1. Non capire bene la sintassi della subquery. Controlla sempre che la subquery faccia riferimento correttamente alla tabella esterna.
  2. Dimenticare il controllo di NULL. Anche se usi EXISTS, a volte devi gestire NULL in modo esplicito.
  3. Mancanza di indice sui campi della subquery. Questo può rallentare molto l'esecuzione della query.

Per oggi è tutto! Ora sai come usare EXISTS e NOT EXISTS per controllare l'esistenza dei dati, e anche le differenze tra questi operatori e IN. Nella prossima lezione continueremo a esplorare le subquery, vedendo come usarle in SELECT per lavorare con dati aggregati.

2
Compito
SQL SELF, livello 13, lezione 3
Bloccato
Ricerca degli studenti senza voti
Ricerca degli studenti senza voti
2
Compito
SQL SELF, livello 13, lezione 3
Bloccato
Verifica dei corsi con studenti iscritti
Verifica dei corsi con studenti iscritti
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION