Antyzłączenia i semizłączenia (NOT EXISTS)
Znajduj „wiersze w A bez dopasowania w B” (antyzłączenie) oraz „wiersze w A z co najmniej jednym dopasowaniem w B” (semizłączenie) za pomocą EXISTS/NOT EXISTS.
Antyzłączenia i semizłączenia (NOT EXISTS) to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Academy zawiera 4 lekcji w sumie.
Semi-join: „ma co najmniej jedno dopasowanie”
Zwracanie wierszy z A, które mają co najmniej jeden pasujący wiersz w B — ale wyłącznie kolumn z A. SQL implementuje semi-join za pomocą EXISTS lub IN.
Semi-join z EXISTS
Użytkownicy, którzy złożyli co najmniej jedno zamówienie:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);Semi-join z IN
Ten sam wynik, inny styl:
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);Dlaczego EXISTS często wygrywa
EXISTS kończy działanie po znalezieniu pierwszego dopasowania dla danego wiersza zewnętrznego. IN może zmaterializować cały zbiór wewnętrzny. Współczesne planisty często optymalizują oba zapytania do tego samego planu, ale EXISTS jest bezpieczniejszym wyborem w przypadku bardzo dużych zbiorów wewnętrznych.
Anti-join: „nie ma dopasowania”
Użytkownicy, którzy NIGDY nie złożyli zamówienia — trzy idiomatyczne postacie:
-- NOT EXISTS (preferred):
SELECT u.* FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- LEFT JOIN ... IS NULL:
SELECT u.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
-- NOT IN (risky with NULLs):
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders);Dlaczego NOT IN jest ryzykowne
Jeśli podzapytanie wewnętrzne zawiera NULL, NOT IN zwraca NULL, a WHERE odrzuca wiersze, dla których predykat ma wartość NULL. Wynik: zero wierszy. NOT EXISTS nie ma tego problemu.
Optymalizacja przez planistę
Współczesny PostgreSQL rozpoznaje EXISTS i NOT EXISTS jako wzorce semi-join i anti-join oraz może wykonywać je za pomocą złączeń haszujących:
EXPLAIN ANALYZE
SELECT u.* FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- → Hash Anti JoinAnti-join z wieloma kolumnami
Należy użyć kluczy złożonych:
SELECT * FROM order_items oi
WHERE NOT EXISTS (
SELECT 1 FROM shipments s
WHERE s.order_id = oi.order_id
AND s.line_no = oi.line_no
);Semi-join z EXISTS i dodatkowym predykatem
Należy dodać filtry do podzapytania wewnętrznego:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
AND o.created_at >= NOW() - INTERVAL '30 days'
);Indeksowanie kolumny korelacji
Zarówno w przypadku EXISTS, jak i NOT EXISTS podzapytanie wewnętrzne filtruje po kluczu wiersza zewnętrznego. Bez indeksu na tym kluczu skanowanie będzie wykonywane dla każdego wiersza zewnętrznego:
CREATE INDEX orders_user_id_idx ON orders(user_id);Kiedy używać LEFT JOIN ... IS NULL
W przypadku pulpitów, które potrzebują również kolumn ze strony bez dopasowania, naturalnym wyborem jest LEFT JOIN. W przypadku czystej semantyki anti-join czytelniejsze jest NOT EXISTS.
Poza SQL: filtry Blooma
W przypadku bardzo dużych anti-joinów pomocny może być wstępny filtr Blooma. PostgreSQL obsługuje indeksy bloom za pośrednictwem rozszerzenia bloom.
Podsumowanie
Semi-join = „ma dopasowanie”; anti-join = „nie ma dopasowania”.
- EXISTS w przypadku semi-join
- NOT EXISTS w przypadku anti-join (bezpieczny dla NULL)
- Należy indeksować kolumnę korelacji.
- Należy unikać NOT IN, chyba że zbiór wewnętrzny nie może zawierać NULL.
Szybkie sprawdzenie
Potrzebują Państwo użytkowników, którzy NIGDY nie złożyli zamówienia. Które rozwiązanie SQL jest najbezpieczniejsze i najbardziej idiomatyczne?
Często zadawane pytania
Czy lekcja „Antyzłączenia i semizłączenia (NOT EXISTS)” jest bezpłatna?
Tak — pełny tekst „Antyzłączenia i semizłączenia (NOT EXISTS)” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Academy, przejdź na CoddyKit PRO. Kurs SQL Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Antyzłączenia i semizłączenia (NOT EXISTS)”?
Znajduj „wiersze w A bez dopasowania w B” (antyzłączenie) oraz „wiersze w A z co najmniej jednym dopasowaniem w B” (semizłączenie) za pomocą EXISTS/NOT EXISTS. Ćwiczysz SQL Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Academy?
Nie wymagamy żadnego doświadczenia. SQL Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Antyzłączenia i semizłączenia (NOT EXISTS)”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Academy?
Tak. Każda lekcja SQL Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Złączenia krzyżowe i iloczyny kartezjańskie
- Złączenia lateralne (LATERAL JOIN)
- Antyzłączenia i semizłączenia (NOT EXISTS)
- Dostrajanie wydajności złączeń wielu tabel