13.2.11.6 Subqueries with EXISTS or NOT EXISTS
Jeżeli podzapytanie zwraca w ogóle jakiekolwiek wiersze, EXISTS to subqueryTRUE, a NOT EXISTS to subqueryFALSE. 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 xTRUE 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.