13.2.11.6 Subquery con EXISTS o NOT EXISTS
Se una subquery restituisce qualche riga, EXISTS
è subquery
TRUE
, e NOT EXISTS
è subquery
FALSE
. Per esempio:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
Tradizionalmente, una EXISTS
subquery inizia con SELECT *
, ma potrebbe iniziare con SELECT 5
o SELECT column1
o qualsiasi altra cosa. MySQL ignora la lista SELECT
in una tale subquery, quindi non fa differenza.
Per l’esempio precedente, se t2
contiene qualsiasi riga, anche righe con nient’altro che valori NULL
, la condizione EXISTS
TRUE
. Questo è in realtà un esempio improbabile perché una EXISTS
subquery contiene quasi sempre delle correlazioni. Ecco alcuni esempi più realistici:
-
Che tipo di negozio è presente in una o più città?
SELECT DISTINCT store_type FROM stores WHERE EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
-
Che tipo di negozio è presente in nessuna città?
SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
-
Che tipo di negozio è presente in tutte le città?
SELECT DISTINCT store_type FROM stores s1 WHERE NOT EXISTS ( SELECT * FROM cities WHERE NOT EXISTS ( SELECT * FROM cities_stores WHERE cities_stores.city = cities.city AND cities_stores.store_type = stores.store_type));
L’ultimo esempio è una query NOT EXISTS
a doppio annidamento. Cioè, ha una clausola NOT EXISTS
dentro una clausola NOT EXISTS
. Formalmente, risponde alla domanda “esiste una città con un negozio che non è in Stores
“? Ma è più facile dire che un NOT EXISTS
annidato risponde alla domanda “è x
TRUE
per tutti i y
?”
In MySQL 8.0.19 e successivi, è anche possibile utilizzare NOT EXISTS
o NOT EXISTS
con TABLE
nella subquery, come questo:
SELECT column1 FROM t1 WHERE EXISTS (TABLE t2);
I risultati sono gli stessi di quando si usa SELECT *
senza la clausola WHERE
nella subquery.