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 DESCzachowuje najświeższy rekord.ORDER BY created_at ASCzachowuje oryginalny rekord.ORDER BY id ASCzachowuje 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 rnFizyczne 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 BYrzeczywiś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 rnSzybkie 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_NUMBERpodzielone na partycje według klucza; należy zachowaćrn = 1. - Element
ORDER BYfunkcji okna wybiera kanoniczną kopię; należy dodać unikalne kryterium rozstrzygające remis. - Wiersze
rn > 1należ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
- Wiersze Top-N dla każdej grupy za pomocą ROW_NUMBER
- Obsługa remisów w Top-N
- Bezpieczne usuwanie duplikatów wierszy
- Zachowywanie najnowszego wiersza dla każdego klucza