Trovare le righe senza corrispondenza (anti-join)
Il pattern LEFT JOIN / IS NULL per trovare record orfani e dati mancanti
Trovare le righe senza corrispondenza (anti-join) è una lezione SQL Interview Prep gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento SQL Interview Prep, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso SQL Interview Prep include 4 lezioni in totale.
La domanda sull'anti-join
Una delle domande più frequenti sui JOIN esterni è: «Trovi i clienti che non hanno mai effettuato un ordine.» Oppure: «Elenca i prodotti che non sono mai stati venduti» o «gli ordini senza un cliente corrispondente».
Tutti questi casi hanno la stessa struttura: righe in una tabella senza corrispondenza in un'altra. L'idioma più chiaro è l'anti-join, costruito con un LEFT JOIN e un filtro IS NULL.
L'idea fondamentale
Parta da un LEFT JOIN: mantiene ogni riga a sinistra e assegna NULL nelle colonne della tabella a destra alle righe senza corrispondenza.
Le righe senza corrispondenza sono quindi esattamente quelle in cui una colonna della tabella a destra è NULL. Applichi questo filtro per isolare le righe senza corrispondenza. Questo è tutto il meccanismo.
Costruire lo schema
Ecco l'anti-join canonico per trovare i clienti senza ordini. Lo legga in due passaggi: LEFT JOIN mantiene tutti i clienti, poi WHERE o.customer_id IS NULL conserva soltanto quelli senza corrispondenza.
SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id
WHERE o.customer_id IS NULL;
-- only customers with zero ordersPerché funziona, passo dopo passo
Segua l'esecuzione con i nostri dati, dove Carol non ha ordini:
- LEFT JOIN produce Alice (x2), Bob (x1) e Carol con le colonne a destra impostate a NULL.
WHERE o.customer_id IS NULLscarta Alice e Bob (le loro colonne a destra contengono valori reali).- Sopravvive solo la riga di Carol, quella con i NULL sintetizzati.
Il filtro viene applicato dopo il JOIN, quindi vede quei NULL e seleziona precisamente le righe orfane.
Scegliere la colonna giusta da verificare
Verifichi una colonna della tabella a destra che in una corrispondenza reale non possa mai essere legittimamente NULL, idealmente la chiave di JOIN o la chiave primaria.
Se verificasse una colonna nullable a destra come o.shipped_at, includerebbe anche gli ordini esistenti ma non ancora spediti: sarebbe una risposta errata. Verificare o.customer_id (la chiave di JOIN) o o.id (la chiave primaria) garantisce che NULL significhi «nessuna riga corrispondente».
-- SAFE: join key / primary key
WHERE o.id IS NULL
-- RISKY: a nullable data column
WHERE o.shipped_at IS NULL -- catches unshipped too!Anti-join e NOT IN
Gli intervistatori confrontano l'anti-join con NOT IN. Sembrano equivalenti, ma si comportano diversamente in presenza di NULL.
Se la sottoquery restituisce anche un solo NULL, NOT IN non restituisce alcuna riga: è un noto bug silenzioso. L'anti-join LEFT JOIN / IS NULL non presenta questo problema.
-- DANGEROUS if any customer_id is NULL
SELECT id, name FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);
-- SAFE anti-join, same intent
SELECT c.id, c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;Anti-join e NOT EXISTS
L'altra alternativa equivalente è NOT EXISTS con una sottoquery correlata. Gestisce correttamente anche i NULL ed è spesso altrettanto veloce.
Tutte e tre le forme (LEFT JOIN/IS NULL, NOT EXISTS, NOT IN) possono esprimere un anti-join, ma in un colloquio preferisca LEFT JOIN/IS NULL o NOT EXISTS perché gestiscono i NULL in modo sicuro. Menzionare il problema di NOT IN fa guadagnare punti.
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);Un errore comune
Un errore frequente consiste nell'inserire la condizione di assenza di corrispondenza nella clausola ON invece che in WHERE.
Scrivere ... ON o.customer_id = c.id AND o.id IS NULL non filtra il risultato: cambia soltanto ciò che viene considerato una corrispondenza e ogni cliente continua a essere restituito dal LEFT JOIN. Il test IS NULL deve trovarsi in WHERE, applicato dopo il JOIN. Analizzeremo completamente questo problema nella lezione successiva.
Trovare le righe figlie orfane
Lo schema funziona anche nella direzione opposta. Per trovare ordini che fanno riferimento a un cliente mancante (righe orfane, in un controllo di integrità dei dati), preservi orders e verifichi che il lato del cliente sia NULL.
SELECT o.id AS order_id, o.customer_id
FROM orders o
LEFT JOIN customers c
ON c.id = o.customer_id
WHERE c.id IS NULL;
-- orders pointing to a non-existent customerContare le righe orfane
Spesso viene richiesto soltanto un conteggio: «Quanti clienti non hanno mai effettuato un ordine?» Incapsuli l'anti-join oppure esegua direttamente il conteggio.
Poiché l'anti-join restituisce già una riga per ogni elemento orfano, qui un semplice COUNT(*) è corretto: c'è esattamente una riga per ogni cliente senza corrispondenza.
SELECT COUNT(*) AS never_ordered
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;Il modello riutilizzabile
Memorizzi questo schema di tre righe: risolve un'enorme quantità di domande da colloquio:
FROM keep_table kLEFT JOIN other o ON o.fk = k.idWHERE o.id IS NULL
Sostituisca tabelle e chiavi per trovare prodotti mai venduti, ticket non assegnati, utenti che non hanno mai effettuato l'accesso e qualsiasi altro caso descritto come «X senza una Y corrispondente».
Verifica rapida
Servono i prodotti che non sono mai comparsi in order_items.
Riepilogo
L'anti-join trova le righe senza corrispondenza: LEFT JOIN seguito da WHERE right_key IS NULL.
- Verifichi la chiave di JOIN o la chiave primaria, mai una colonna dati nullable.
- Il test
IS NULLappartiene aWHERE, non aON. - È equivalente a
NOT EXISTS; lo preferisca aNOT IN, che presenta problemi in presenza di NULL. - Inverta le tabelle per trovare le righe figlie orfane.
Un solo modello, molte domande: «X senza una Y corrispondente».
Domande Frequenti
La lezione «Trovare le righe senza corrispondenza (anti-join)» è gratuita?
Sì — il testo completo di «Trovare le righe senza corrispondenza (anti-join)» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso SQL Interview Prep, passa a CoddyKit PRO. Il corso SQL Interview Prep include 4 lezioni in totale.
Cosa imparerò in «Trovare le righe senza corrispondenza (anti-join)»?
Il pattern LEFT JOIN / IS NULL per trovare record orfani e dati mancanti Eserciti SQL Interview Prep con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare SQL Interview Prep?
Non è richiesta alcuna esperienza precedente. SQL Interview Prep su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Trovare le righe senza corrispondenza (anti-join)»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione SQL Interview Prep?
Sì. Ogni lezione SQL Interview Prep include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- LEFT JOIN e conservazione delle righe senza corrispondenza
- Semantica di RIGHT e FULL OUTER JOIN
- Trovare le righe senza corrispondenza (anti-join)
- La trappola di WHERE sui full outer join