0Pricing
Coding Interview Prep · Lezione

EXISTS e NOT EXISTS correlati

L'alternativa robusta all'anti-join che gestisce correttamente i NULL

EXISTS e NOT EXISTS correlati è una lezione Coding 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 Coding Interview Prep, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Coding Interview Prep include 4 lezioni in totale.

EXISTS verifica la presenza

EXISTS riceve una sottoquery e restituisce TRUE non appena quella sottoquery produce almeno una riga, altrimenti FALSE. Non restituisce mai le righe in sé.

Con una sottoquery correlata al suo interno, EXISTS diventa un test di presenza per ogni riga esterna: «esiste una riga corrispondente a questa riga esterna?»

Poiché si interrompe alla prima corrispondenza, non importa quante righe corrispondano. Questo dettaglio semantico è uno dei preferiti nei colloqui.

Una EXISTS correlata di base

Trovi i clienti che hanno effettuato almeno un ordine. La query interna è correlata tramite o.customer_id = c.customer_id.

Per ogni cliente, EXISTS chiede: esiste un ordine per questo cliente? Se sì, mantiene il cliente.

SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
);

Perché usare SELECT 1 dentro EXISTS

Dentro EXISTS vedrà SELECT 1, SELECT * oppure SELECT NULL. Sono tutti equivalenti.

EXISTS verifica soltanto se vengono restituite delle righe, mai il loro contenuto, quindi le colonne proiettate sono irrilevanti. L'ottimizzatore le ignora.

SELECT 1 è una convenzione comune che segnala l'intento: «mi interessa solo l'esistenza». Ne scelga uno e sia coerente; non lasci credere all'intervistatore che l'elenco delle colonne sia importante in questo caso.

NOT EXISTS trova ciò che manca

NOT EXISTS inverte il test: mantiene la riga esterna solo quando la sottoquery correlata non restituisce nessuna riga.

Questo è il classico anti-join: clienti senza ordini, prodotti mai venduti, studenti senza consegne.

SELECT c.customer_id, c.name
FROM customers c
WHERE NOT EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
);

La trappola di NULL con NOT IN

Questo è un punto chiave nei colloqui. NOT IN applicato a una sottoquery che può contenere NULL ha un comportamento insidioso: se l'elenco contiene anche un solo NULL, NOT IN non restituisce nessuna riga.

Succede perché un confronto con NULL restituisce UNKNOWN e NOT IN richiede che ogni confronto sia falso. Un solo UNKNOWN compromette l'intera condizione.

NOT EXISTS non presenta questo problema: verifica semplicemente la presenza di righe e gestisce NULL in modo sicuro.

-- Risky: returns nothing if any o.customer_id is NULL
SELECT c.customer_id FROM customers c
WHERE c.customer_id NOT IN (SELECT o.customer_id FROM orders o);

-- Safe: NULLs do not break it
SELECT c.customer_id FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
);

Perché NOT EXISTS è sicura rispetto a NULL

Il motivo sta nella logica della corrispondenza. NOT EXISTS verifica se esiste una riga interna che soddisfa o.customer_id = c.customer_id.

Una riga in cui o.customer_id è NULL non soddisfa mai quell'uguaglianza (NULL = qualsiasi valore restituisce UNKNOWN, non TRUE), quindi non viene semplicemente considerata una corrispondenza. Il test di presenza resta corretto.

Con NOT IN, lo stesso NULL entra a far parte di un confronto con un elenco il cui risultato UNKNOWN elimina ogni riga dall'output. Ecco perché nei colloqui tecnici avanzati si preferisce NOT EXISTS.

EXISTS con condizioni aggiuntive

La sottoquery correlata può contenere ulteriori predicati. Trovi i clienti che hanno effettuato almeno un ordine superiore a 1000.

La condizione aggiuntiva si trova all'interno della sottoquery EXISTS, con ambito riferito a ciascun cliente.

SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
      AND o.amount > 1000
);

Prestazioni: comportamento short-circuit

EXISTS può interrompere la scansione della relazione interna non appena trova una riga corrispondente. Non crea né conta un insieme di risultati completo.

Per questo EXISTS è generalmente efficiente, soprattutto quando la colonna correlata è indicizzata, perché ogni ricerca per riga può trovare rapidamente una corrispondenza e terminare subito.

Lo confronti con un COUNT(*) > 0 correlato, che obbliga a contare tutte le corrispondenze. Preferisca EXISTS quando Le serve solo una risposta sì/no.

EXISTS e COUNT per verificare la presenza

A volte i candidati scrivono un conteggio correlato per verificare la presenza. Funziona, ma comporta lavoro inutile.

La versione con COUNT conta ogni ordine corrispondente; EXISTS si interrompe dopo il primo. Per una semplice verifica di esistenza, EXISTS comunica meglio l'intento e consente all'ottimizzatore di applicare lo short-circuit.

-- Works but counts everything
SELECT c.customer_id FROM customers c
WHERE (SELECT COUNT(*) FROM orders o
       WHERE o.customer_id = c.customer_id) > 0;

-- Better: stops at first match
SELECT c.customer_id FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o
              WHERE o.customer_id = c.customer_id);

Esempio svolto: prodotti mai ordinati

Una classica domanda da colloquio sugli anti-join: elencare i prodotti che non sono mai stati ordinati. NOT EXISTS esprime il requisito quasi come in inglese.

Per ogni prodotto, verifichi se esiste una riga d'ordine che lo riferisce; conservi solo quelli senza alcuna corrispondenza.

SELECT p.product_id, p.name
FROM products p
WHERE NOT EXISTS (
    SELECT 1
    FROM order_items oi
    WHERE oi.product_id = p.product_id
);

EXISTS in NOT EXISTS per query in stile divisione

Annidare EXISTS dentro NOT EXISTS esprime la divisione relazionale: "trovare le righe che corrispondono a tutti gli elementi di un insieme". Una domanda classica è: "clienti che hanno ordinato ogni prodotto di una categoria".

La logica è la seguente: conservi un cliente quando non esiste alcun prodotto che non abbia ordinato. Questa doppia negazione è il tratto distintivo di una query di divisione e gli intervistatori la usano per verificare una conoscenza approfondita di EXISTS.

SELECT c.customer_id
FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM products p
    WHERE p.category = 'Coffee'
      AND NOT EXISTS (
          SELECT 1 FROM order_items oi
          JOIN orders o ON o.order_id = oi.order_id
          WHERE oi.product_id = p.product_id
            AND o.customer_id = c.customer_id
      )
);

Controllo rapido

Scelga il modo più sicuro per trovare i clienti senza ordini.

Riepilogo: EXISTS e NOT EXISTS correlati

Punti chiave:

  • EXISTS verifica la presenza per ogni riga e applica lo short-circuit alla prima corrispondenza; la scelta della colonna al suo interno è irrilevante (utilizzi SELECT 1).
  • NOT EXISTS è l'anti-join sicuro rispetto ai NULL per trovare le righe senza corrispondenza.
  • NOT IN con un NULL nell'elenco restituisce nulla; preferisca NOT EXISTS.
  • Per verificare l'esistenza, EXISTS è preferibile a un COUNT(*) > 0 correlato perché si interrompe in anticipo.

Menzioni spontaneamente il problema dei NULL con NOT IN: è un segnale affidabile di maturità nell'uso di SQL.

Domande Frequenti

La lezione «EXISTS e NOT EXISTS correlati» è gratuita?

Sì — il testo completo di «EXISTS e NOT EXISTS correlati» è 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 Coding Interview Prep, passa a CoddyKit PRO. Il corso Coding Interview Prep include 4 lezioni in totale.

Cosa imparerò in «EXISTS e NOT EXISTS correlati»?

L'alternativa robusta all'anti-join che gestisce correttamente i NULL Eserciti Coding 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 Coding Interview Prep?

Non è richiesta alcuna esperienza precedente. Coding 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 «EXISTS e NOT EXISTS correlati»?

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 Coding Interview Prep?

Sì. Ogni lezione Coding 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

  1. Anatomia di una sottoquery correlata
  2. Aggregati per gruppo senza GROUP BY
  3. EXISTS e NOT EXISTS correlati
  4. Riscrivere le sottoquery correlate come join
← Torna a Coding Interview Prep