0Pricing
Coding Interview Prep · Lekcja

Znajdowanie wierszy bez dopasowania (anti-join)

Wzorzec LEFT JOIN / IS NULL do znajdowania osieroconych i brakujących danych

Znajdowanie wierszy bez dopasowania (anti-join) to bezpłatna lekcja Coding Interview Prep 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 Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Pytanie o złączenie antysemi

Jedno z najczęściej zadawanych pytań dotyczących złączeń zewnętrznych brzmi: „Znajdź klientów, którzy nigdy nie złożyli zamówienia”. Albo: „Wymień produkty, których nigdy nie sprzedano” czy „zamówienia bez pasującego klienta”.

Wszystkie te zadania mają wspólny schemat: wiersze z jednej tabeli, które nie mają dopasowania w innej tabeli. Czystym idiomem jest złączenie antysemi, zbudowane z LEFT JOIN oraz filtra IS NULL.

Główna idea

Należy zacząć od LEFT JOIN: zachowuje on każdy wiersz z lewej tabeli, a w niedopasowanych wierszach wstawia NULL do kolumn prawej tabeli.

Niedopasowane wiersze to więc dokładnie te, w których kolumna prawej tabeli ma wartość NULL. Wystarczy je odfiltrować, aby wyodrębnić wiersze bez dopasowania. Na tym polega cała sztuczka.

Budowanie schematu

Oto kanoniczne złączenie antysemi wyszukujące klientów bez zamówień. Należy odczytać je w dwóch krokach: LEFT JOIN zachowuje wszystkich klientów, a następnie WHERE o.customer_id IS NULL pozostawia tylko niedopasowanych.

SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
WHERE o.customer_id IS NULL;
-- only customers with zero orders

Dlaczego to działa — krok po kroku

Prześledźmy to na naszych danych, w których Carol nie ma zamówień:

  • LEFT JOIN tworzy wiersze Alice (x2), Bob (x1) oraz Carol z wartościami NULL w kolumnach prawej tabeli.
  • WHERE o.customer_id IS NULL odrzuca Alice i Boba (ich kolumny prawej tabeli zawierają rzeczywiste wartości).
  • Pozostaje tylko wiersz Carol — ten, w którym wartości NULL zostały dodane przez złączenie.

Filtr jest wykonywany po złączeniu, więc widzi te wartości NULL i wybiera dokładnie rekordy osierocone.

Wybór właściwej kolumny do sprawdzenia

Należy sprawdzać kolumnę prawej tabeli, która w rzeczywistym dopasowaniu nigdy nie może zgodnie z założeniami mieć wartości NULL — najlepiej klucz złączenia lub klucz główny.

Sprawdzenie kolumny, która może przyjmować NULL, takiej jak o.shipped_at, znalazłoby również istniejące, ale niewysłane zamówienia, co byłoby błędną odpowiedzią. Sprawdzenie o.customer_id (klucza złączenia) lub o.id (klucza głównego) gwarantuje, że NULL oznacza brak dopasowanego wiersza.

-- SAFE: join key / primary key
WHERE o.id IS NULL

-- RISKY: a nullable data column
WHERE o.shipped_at IS NULL  -- catches unshipped too!

Złączenie antysemi a NOT IN

Osoby prowadzące rozmowy rekrutacyjne porównują złączenie antysemi z NOT IN. Wyglądają one na równoważne, ale różnią się zachowaniem w przypadku wartości NULL.

Jeśli podzapytanie zwróci choć jedną wartość NULL, NOT IN nie zwróci żadnych wierszy — jest to osławiony, trudny do wykrycia błąd. Złączenie antysemi LEFT JOIN / IS NULL jest na niego odporne.

-- DANGEROUS if any customer_id is NULL
SELECT id, name FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);

-- SAFE anti-join, same intent
SELECT c.id, c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

Złączenie antysemi a NOT EXISTS

Innym równoważnym rozwiązaniem jest NOT EXISTS ze skorelowanym podzapytaniem. Ono również prawidłowo obsługuje wartości NULL i często jest równie szybkie.

Wszystkie trzy rozwiązania (LEFT JOIN/IS NULL, NOT EXISTS, NOT IN) mogą wyrażać złączenia antysemi, ale podczas rozmowy warto preferować LEFT JOIN/IS NULL lub NOT EXISTS ze względu na bezpieczeństwo w przypadku NULL. Wspomnienie o pułapce NOT IN będzie dodatkowym atutem.

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

Częsty błąd

Częsty błąd polega na umieszczeniu warunku braku dopasowania w klauzuli ON zamiast w WHERE.

Zapis ... ON o.customer_id = c.id AND o.id IS NULL nie filtruje wyniku; jedynie zmienia to, co jest uznawane za dopasowanie, a każdy klient nadal pozostaje w wyniku LEFT JOIN. Sprawdzenie IS NULL musi znajdować się w WHERE i być stosowane po złączeniu. W następnej lekcji szczegółowo omówimy tę pułapkę.

Wyszukiwanie osieroconych wierszy podrzędnych

Ten schemat działa również w przeciwnym kierunku. Aby znaleźć zamówienia odwołujące się do nieistniejącego klienta (rekordy osierocone, kontrola integralności danych), należy zachować tabelę orders i sprawdzić, czy po stronie klientów występuje NULL.

SELECT o.id AS order_id, o.customer_id
FROM orders o
LEFT JOIN customers c
  ON c.id = o.customer_id
WHERE c.id IS NULL;
-- orders pointing to a non-existent customer

Zliczanie rekordów osieroconych

Często wymagane jest tylko zliczenie: „Ilu klientów nigdy nie złożyło zamówienia?” Można opakować złączenie antysemi w podzapytanie albo zliczyć wiersze bezpośrednio.

Ponieważ złączenie antysemi już zwraca jeden wiersz na każdy rekord osierocony, zwykłe COUNT(*) jest tutaj poprawne — na każdego niedopasowanego klienta przypada dokładnie jeden wiersz.

SELECT COUNT(*) AS never_ordered
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

Uniwersalny szablon

Proszę zapamiętać ten trzywierszowy schemat; rozwiązuje on ogromną klasę pytań rekrutacyjnych:

  • FROM keep_table k
  • LEFT JOIN other o ON o.fk = k.id
  • WHERE o.id IS NULL

Wystarczy zamienić tabele i klucze, aby znaleźć niesprzedane produkty, nieprzypisane zgłoszenia, użytkowników bez logowań oraz wszystko, co opisano jako „X bez pasującego Y”.

Szybkie sprawdzenie

Należy znaleźć produkty, które nigdy nie pojawiły się w tabeli order_items.

Podsumowanie

Złączenie antysemi znajduje wiersze bez dopasowania: LEFT JOIN, a następnie WHERE right_key IS NULL.

  • Należy sprawdzać klucz złączenia lub klucz główny, nigdy kolumnę danych, która może przyjmować NULL.
  • Sprawdzenie IS NULL należy umieścić w WHERE, a nie w ON.
  • Jest równoważne z NOT EXISTS; należy preferować je zamiast NOT IN, które nie działa poprawnie w obecności wartości NULL.
  • Aby znaleźć osierocone wiersze podrzędne, należy odwrócić kolejność tabel.

Jeden szablon rozwiązuje wiele pytań: „X bez pasującego Y”.

Często zadawane pytania

Czy lekcja „Znajdowanie wierszy bez dopasowania (anti-join)” jest bezpłatna?

Tak — pełny tekst „Znajdowanie wierszy bez dopasowania (anti-join)” 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 Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Co nauczysz się w „Znajdowanie wierszy bez dopasowania (anti-join)”?

Wzorzec LEFT JOIN / IS NULL do znajdowania osieroconych i brakujących danych Ćwiczysz Coding Interview Prep 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ąć Coding Interview Prep?

Nie wymagamy żadnego doświadczenia. Coding Interview Prep 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 „Znajdowanie wierszy bez dopasowania (anti-join)”?

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 Coding Interview Prep?

Tak. Każda lekcja Coding Interview Prep 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

  1. LEFT JOIN i zachowywanie niedopasowanych wierszy
  2. Semantyka RIGHT i FULL OUTER JOIN
  3. Znajdowanie wierszy bez dopasowania (anti-join)
  4. Pułapka WHERE w złączeniu zewnętrznym
← Powrót do Coding Interview Prep