0Pricing
SQL Academy · Lezione

EXISTS e NOT EXISTS

Verifichi in modo efficiente la presenza di righe correlate

EXISTS e NOT EXISTS è una lezione SQL Academy gratuita su CoddyKit. Questa è la lezione 2 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 Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso SQL Academy include 4 lezioni in totale.

Che cos'è EXISTS?

L'operatore EXISTS verifica se una sottoquery restituisce almeno una riga. Il risultato è TRUE se la sottoquery produce un risultato qualsiasi e FALSE se è vuota.

A differenza degli altri operatori per sottoquery, che confrontano valori, EXISTS considera solo la presenza: non esamina i dati effettivamente restituiti dalla sottoquery.

Configurazione delle tabelle di esempio

Prima di scrivere query con EXISTS, vengono create due tabelle: customers e orders. Verranno utilizzate in tutta la lezione per analizzare il funzionamento di EXISTS e NOT EXISTS nella pratica.

CREATE TABLE customers (
  customer_id INT PRIMARY KEY,
  name        VARCHAR(100),
  country     VARCHAR(50)
);

CREATE TABLE orders (
  order_id    INT PRIMARY KEY,
  customer_id INT,
  amount      DECIMAL(10,2),
  order_date  DATE
);

INSERT INTO customers VALUES
  (1, 'Alice',   'US'),
  (2, 'Bob',     'UK'),
  (3, 'Charlie', 'US'),
  (4, 'Diana',   'DE');

INSERT INTO orders VALUES
  (101, 1, 250.00, '2024-01-10'),
  (102, 1, 180.00, '2024-02-15'),
  (103, 2,  95.00, '2024-03-01'),
  (104, 3, 430.00, '2024-03-22');

Sintassi di base di EXISTS

La sintassi di base di EXISTS lo colloca all'interno di una clausola WHERE. La sottoquery contenuta in EXISTS fa solitamente riferimento a una colonna della query esterna: si tratta di una sottoquery correlata.

La query seguente individua ogni cliente che ha effettuato almeno un ordine.

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

SELECT 1 all'interno di EXISTS

Forse avrete notato che la sottoquery usa SELECT 1 invece di selezionare una colonna reale qualsiasi. È intenzionale: EXISTS controlla solo se le righe esistono, non il loro contenuto.

L'uso di SELECT 1 (o persino di SELECT *) non cambia il risultato, ma SELECT 1 comunica chiaramente sia al motore del database sia a chi legge che i valori effettivi non sono importanti.

-- Both of these return the same result
SELECT name FROM customers c
WHERE EXISTS (SELECT 1   FROM orders o WHERE o.customer_id = c.customer_id);

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

Come il database valuta EXISTS

Per ogni riga della query esterna, il database esegue la sottoquery correlata. Non appena trova una riga corrispondente, il motore interrompe la scansione e imposta EXISTS su TRUE: questa valutazione a cortocircuito rende EXISTS molto efficiente anche su tabelle di grandi dimensioni.

Al contrario, un JOIN costruirebbe l'insieme completo delle righe corrispondenti prima di applicare il filtro, il che può essere più lento quando vi serve solo sapere se esiste una corrispondenza.

-- EXISTS short-circuits after first match
-- Efficient even when orders table has millions of rows
SELECT name, country
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
    AND o.amount > 200
);

NOT EXISTS: trovare le righe assenti

NOT EXISTS è l'inverso: restituisce TRUE quando la sottoquery non trova nessuna riga corrispondente. È il modo SQL standard per rispondere a domande come "quali clienti non hanno mai effettuato un ordine?"

Tentare di risolvere il problema con un JOIN normale o con NOT IN può produrre risultati errati quando sono coinvolti valori NULL: NOT EXISTS evita completamente questo problema.

-- Customers who have NOT placed any order
SELECT customer_id, name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
);

NOT EXISTS e NOT IN con i NULL

Un vantaggio fondamentale di NOT EXISTS rispetto a NOT IN è la gestione sicura dei NULL. Se la sottoquery usata da NOT IN restituisce anche un solo NULL, l'intera espressione NOT IN diventa NULL, il che significa che la query esterna non restituisce alcuna riga.

NOT EXISTS non è soggetto a questo problema perché valuta l'esistenza delle righe, non l'uguaglianza dei valori.

-- Dangerous: if any customer_id in orders is NULL,
-- NOT IN returns zero rows!
SELECT name FROM customers
WHERE customer_id NOT IN (SELECT customer_id FROM orders);

-- Safe: NOT EXISTS handles NULLs correctly
SELECT name FROM customers c
WHERE NOT EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.customer_id
);

EXISTS con più condizioni

La sottoquery all'interno di EXISTS può contenere qualsiasi SQL valido, incluse più condizioni WHERE. Questo vi permette di cercare righe correlate molto specifiche, ad esempio clienti che hanno effettuato un ordine superiore a una determinata soglia in un mese specifico.

-- Customers who placed an order over 200 in March 2024
SELECT c.name, c.country
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
    AND o.amount > 200
    AND o.order_date >= '2024-03-01'
    AND o.order_date <  '2024-04-01'
);

EXISTS in DELETE e UPDATE

EXISTS non è limitato alle istruzioni SELECT. Potete usarlo in UPDATE e DELETE per modificare o rimuovere righe in base all'esistenza di dati correlati in un'altra tabella.

L'esempio seguente elimina gli ordini appartenenti a clienti di un determinato Paese.

-- Delete orders placed by US customers
DELETE FROM orders o
WHERE EXISTS (
  SELECT 1
  FROM customers c
  WHERE c.customer_id = o.customer_id
    AND c.country = 'US'
);

Confrontare EXISTS con un JOIN

EXISTS e JOIN possono spesso esprimere la stessa domanda, ma si comportano in modo diverso. Un JOIN duplica le righe quando esistono più corrispondenze; EXISTS restituisce ogni riga esterna al massimo una volta.

Quando vi serve solo sapere se esiste una relazione, senza recuperare dati dalla tabella correlata, EXISTS è più semplice e in genere più veloce.

-- JOIN may return duplicate customer rows if a customer has multiple orders
SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id;

-- EXISTS always returns each customer once
SELECT c.name
FROM customers c
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.customer_id
);

NOT EXISTS per i controlli di qualità dei dati

NOT EXISTS è uno strumento efficace per verificare la qualità dei dati. Potete usarlo per trovare record orfani, riferimenti mancanti o righe che dovrebbero avere dati correlati ma non li hanno.

La query seguente rileva le righe degli ordini il cui customer_id non corrisponde ad alcuna riga nella tabella customers: un segnale di integrità referenziale compromessa.

-- Find orders with no matching customer (orphaned records)
SELECT o.order_id, o.customer_id, o.amount
FROM orders o
WHERE NOT EXISTS (
  SELECT 1
  FROM customers c
  WHERE c.customer_id = o.customer_id
);

Verifica rapida

Verificate la vostra comprensione di EXISTS e NOT EXISTS.

Riepilogo della lezione

In questa lezione avete imparato come EXISTS e NOT EXISTS permettano di verificare la presenza o l'assenza di righe correlate senza confrontare direttamente i valori.

Punti chiave:

  • EXISTS restituisce TRUE non appena la sottoquery trova una riga corrispondente (valutazione a cortocircuito).
  • NOT EXISTS restituisce TRUE quando la sottoquery non trova alcuna riga corrispondente.
  • Usate SELECT 1 all'interno di EXISTS: i valori restituiti sono irrilevanti.
  • NOT EXISTS gestisce i NULL in modo sicuro; NOT IN no: preferite NOT EXISTS quando potrebbero essere presenti valori NULL.
  • EXISTS funziona nelle istruzioni SELECT, UPDATE e DELETE.
  • Quando vi serve solo verificare l'esistenza, EXISTS è spesso più semplice e veloce di un JOIN.

Domande Frequenti

La lezione «EXISTS e NOT EXISTS» è gratuita?

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

Cosa imparerò in «EXISTS e NOT EXISTS»?

Verifichi in modo efficiente la presenza di righe correlate Eserciti SQL Academy 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 Academy?

Non è richiesta alcuna esperienza precedente. SQL Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «EXISTS e NOT EXISTS»?

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 Academy?

Sì. Ogni lezione SQL Academy 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. Sottoquery correlate
  2. EXISTS e NOT EXISTS
  3. IN a confronto con ANY e ALL
  4. Prestazioni di EXISTS e JOIN
← Torna a SQL Academy