0Pricing
Coding Interview Prep · Lekcja

Bezpieczne usuwanie duplikatów wierszy

Usuwanie identycznych i prawie identycznych wierszy z zachowaniem jednego kanonicznego rekordu

Bezpieczne usuwanie duplikatów wierszy 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.

Problem duplikacji

„Ta tabela zawiera zduplikowane wiersze. Należy je usunąć, ale zachować po jednej kopii każdego z nich”. Niemal każda rozmowa rekrutacyjna na stanowisko inżyniera danych obejmuje jakiś wariant tego zadania. Trudność polega na wykonaniu go bezpiecznie: zachowaniu dokładnie jednego kanonicznego wiersza i uniknięciu przypadkowego usunięcia różnych rekordów, które tylko wyglądają podobnie.

Omówimy wykrywanie duplikatów, wybór kopii, którą należy zachować, usuwanie duplikatów w zapytaniu SELECT oraz fizyczne usuwanie duplikatów z tabeli.

Najpierw zdefiniuj duplikat

Pierwsze pytanie, które należy zadać rekruterowi, brzmi: „Co sprawia, że dwa wiersze są duplikatami?” Możliwe odpowiedzi to:

  • Dokładne duplikaty: każda kolumna ma identyczną wartość.
  • Duplikaty klucza: taki sam klucz biznesowy, na przykład takie samo email, ale wartości innych kolumn mogą się różnić.

Technika zależy od wybranej definicji. Nie należy niczego zakładać — jej doprecyzowanie to najważniejszy krok, a rekruterzy oczekują, że zostanie o to zadane pytanie.

Wykrywanie duplikatów

Aby znaleźć zduplikowane klucze, należy grupować według kolumn definiujących duplikat i zachować grupy, których liczność jest większa od jednego. Dzięki temu wiadomo, których kluczy dotyczy problem i ile kopii istnieje, zanim zostaną wprowadzone jakiekolwiek zmiany.

Uruchomienie zapytania wykrywającego przed rozpoczęciem usuwania to dobra praktyka, o której warto wspomnieć: pozwala sprawdzić skalę problemu przed usunięciem danych.

SELECT email, COUNT(*) AS copies
FROM users
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY copies DESC;

Dokładne duplikaty: DISTINCT

Jeśli duplikaty są rzeczywiście identyczne we wszystkich kolumnach, widok bez duplikatów tylko do odczytu można uzyskać za pomocą SELECT DISTINCT *. UNION (bez ALL) również usuwa zduplikowane wiersze.

DISTINCT pomaga jednak tylko wtedy, gdy cały wiersz ma być pozbawiony duplikatów i nie trzeba wybierać, którą kopię zachować. W przypadku duplikatów klucza, gdy wartości kolumn się różnią, potrzebne jest rankingowanie.

-- Read-only dedup of exact-duplicate rows
SELECT DISTINCT customer_id, name, signup_date
FROM customers;

Duplikaty klucza: ROW_NUMBER

Gdy wiersze mają wspólny klucz, ale różnią się wartościami innych kolumn, należy podzielić je na partycje według klucza i ponumerować każdą kopię. rn = 1 oznacza wiersz, który zostanie zachowany, a rn > 1 — dodatkowe wiersze przeznaczone do usunięcia.

Element ORDER BY wewnątrz funkcji okna decyduje o tym, która kopia będzie kanoniczna. Należy wybrać go świadomie, na przykład zachowując wiersz z najnowszą datą aktualizacji.

SELECT *,
  ROW_NUMBER() OVER (
    PARTITION BY email
    ORDER BY updated_at DESC
  ) AS rn
FROM users;

Wybór kanonicznej kopii

Numerowanie należy umieścić w CTE i zachować tylko rn = 1. Zwróci to jeden wiersz na klucz — konkretnie ten, który element ORDER BY umieścił na pierwszym miejscu.

Ta postać zapytania SELECT nie modyfikuje danych. Doskonale nadaje się do utworzenia czystego widoku albo zasilenia tabeli docelowej bez duplikatów za pomocą INSERT ... SELECT, bez dotykania tabeli źródłowej.

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY email ORDER BY updated_at DESC
    ) AS rn
  FROM users
)
SELECT user_id, email, name, updated_at
FROM ranked
WHERE rn = 1;

Znaczenie kolejności

Element ORDER BY wewnątrz partycji to decyzja biznesowa, a nie formalność:

  • ORDER BY updated_at DESC zachowuje najświeższy rekord.
  • ORDER BY created_at ASC zachowuje oryginalny rekord.
  • ORDER BY id ASC zachowuje najniższy klucz zastępczy, co jest przydatne jako stabilny, arbitralny wybór.

Należy dodać unikalne kryterium rozstrzygające remis, aby wybór wiersza był jednoznaczny, gdy podstawowa kolumna sortowania również ma takie same wartości.

ROW_NUMBER() OVER (
  PARTITION BY email
  ORDER BY updated_at DESC, id ASC
) AS rn

Fizyczne usuwanie duplikatów

Aby rzeczywiście usunąć duplikaty z tabeli, należy zidentyfikować dodatkowe wiersze (rn > 1) i je usunąć. W Postgres i SQL Server można usuwać dane za pomocą CTE, a w MySQL często stosuje się samozłączenie lub podzapytanie.

Zawsze należy najpierw uruchomić odpowiadające zapytanie SELECT, aby zobaczyć dokładnie, które wiersze znikną. Usuwanie bez sprawdzenia to najczęstszy powód niepowodzenia kandydatów w tym zadaniu.

WITH ranked AS (
  SELECT ctid,
    ROW_NUMBER() OVER (
      PARTITION BY email ORDER BY updated_at DESC, id ASC
    ) AS rn
  FROM users
)
DELETE FROM users
WHERE ctid IN (SELECT ctid FROM ranked WHERE rn > 1);

Wzorzec usuwania z samozłączeniem

Klasyczne, przenośne podejście zachowuje wiersz z najmniejszą wartością id dla każdego zduplikowanego klucza, a pozostałe usuwa za pomocą samozłączenia. Nie wymaga ono funkcji okna, co ma znaczenie w przypadku starszych silników baz danych.

Warunek złączenia paruje każdy wiersz z innym wierszem, który ma ten sam klucz, ale mniejszą wartość id. Każdy wiersz, dla którego istnieje taki odpowiednik z mniejszym id, jest duplikatem przeznaczonym do usunięcia.

DELETE u1
FROM users u1
JOIN users u2
  ON u1.email = u2.email
 AND u1.id > u2.id;

Lista kontrolna bezpieczeństwa

Przed usunięciem danych należy się zabezpieczyć:

  • Należy umieścić usuwanie w transakcji, aby można było wykonać ROLLBACK, jeśli liczba wierszy okaże się nieprawidłowa.
  • Najpierw należy wykonać SELECT COUNT(*) dla wierszy przeznaczonych do usunięcia i sprawdzić, czy wynik jest rozsądny.
  • Warto rozważyć utworzenie tabeli kopii zapasowej: CREATE TABLE users_bak AS SELECT * FROM users.
  • Należy potwierdzić, że kolumny PARTITION BY rzeczywiście definiują duplikat — w przeciwnym razie można usunąć różne rekordy.
BEGIN;
-- run the DELETE, inspect row count
-- COMMIT; if correct, otherwise ROLLBACK;

Prawie duplikaty i normalizacja

Czasami wiersze nie są dokładnie identyczne, ale logicznie oznaczają to samo: 'Ann@X.com' i 'ann@x.com' albo wartości różniące się końcowymi spacjami. Należy tworzyć partycje na podstawie znormalizowanego wyrażenia, a nie surowej kolumny.

Wspomnienie o normalizacji pokazuje dojrzałość: duplikaty w rzeczywistych danych często ukrywają się za różnicami w wielkości liter, białych znakach lub formatowaniu, których proste porównanie kluczy nie wykrywa.

ROW_NUMBER() OVER (
  PARTITION BY LOWER(TRIM(email))
  ORDER BY updated_at DESC, id ASC
) AS rn

Szybkie sprawdzenie

Należy wybrać bezpieczne podejście do usuwania duplikatów.

Podsumowanie: bezpieczne usuwanie duplikatów

Duplikaty należy usuwać metodycznie:

  • Najpierw należy zdefiniować duplikat, a następnie go wykryć za pomocą GROUP BY / HAVING COUNT(*) > 1.
  • Dokładne duplikaty → DISTINCT. Duplikaty klucza → ROW_NUMBER podzielone na partycje według klucza; należy zachować rn = 1.
  • Element ORDER BY funkcji okna wybiera kanoniczną kopię; należy dodać unikalne kryterium rozstrzygające remis.
  • Wiersze rn > 1 należy usuwać w transakcji, po wcześniejszym sprawdzeniu ich liczby.
  • Należy normalizować klucze, aby wykrywać prawie duplikaty.

Często zadawane pytania

Czy lekcja „Bezpieczne usuwanie duplikatów wierszy” jest bezpłatna?

Tak — pełny tekst „Bezpieczne usuwanie duplikatów wierszy” 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 „Bezpieczne usuwanie duplikatów wierszy”?

Usuwanie identycznych i prawie identycznych wierszy z zachowaniem jednego kanonicznego rekordu Ć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 „Bezpieczne usuwanie duplikatów wierszy”?

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. Wiersze Top-N dla każdej grupy za pomocą ROW_NUMBER
  2. Obsługa remisów w Top-N
  3. Bezpieczne usuwanie duplikatów wierszy
  4. Zachowywanie najnowszego wiersza dla każdego klucza
← Powrót do Coding Interview Prep