13.2.11.6 Subqueries with EXISTS or NOT EXISTS
Jeżeli podzapytanie zwraca w ogóle jakiekolwiek wiersze, EXISTS
to subquery
TRUE
, a NOT EXISTS
to subquery
FALSE
. Na przykład:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
Tradycyjnie, podzapytanie EXISTS
zaczyna się od SELECT *
, ale może zaczynać się od SELECT 5
lub SELECT column1
lub w ogóle od czegokolwiek. MySQL ignoruje listę SELECT
w takim podzapytaniu, więc nie robi to żadnej różnicy.
Dla poprzedniego przykładu, jeśli t2
zawiera jakiekolwiek wiersze, nawet wiersze nie zawierające nic poza wartościami NULL
, warunkiem EXISTS
jest TRUE
. Jest to w rzeczywistości mało prawdopodobny przykład, ponieważ podzapytanie EXISTS
prawie zawsze zawiera korelacje. Oto kilka bardziej realistycznych przykładów:
-
Jaki sklep jest obecny w jednym lub więcej miastach?
SELECT DISTINCT store_type FROM stores WHERE EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
-
Jaki sklep jest obecny w żadnym mieście?
SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
-
Jaki rodzaj sklepu jest obecny we wszystkich miastach?
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));
Ostatni przykład to zapytanie typu double-nested NOT EXISTS
. Oznacza to, że posiada ono klauzulę NOT EXISTS
wewnątrz klauzuli NOT EXISTS
. Formalnie odpowiada to na pytanie „czy istnieje miasto ze sklepem, którego nie ma w Stores
„? Łatwiej jednak powiedzieć, że zagnieżdżona NOT EXISTS
odpowiada na pytanie „czy x
TRUE
dla wszystkich y
?”.
W MySQL 8.0.19 i nowszych, możesz również użyć NOT EXISTS
lub NOT EXISTS
z TABLE
w podzapytaniu, tak jak to:
SELECT column1 FROM t1 WHERE EXISTS (TABLE t2);
Wyniki są takie same jak w przypadku użycia SELECT *
bez WHERE
klauzuli w podzapytaniu.