Mam tabelę z następującymi polami:
id (Unique)
url (Unique)
title
company
site_id
Teraz muszę usunąć wiersze mające takie same title, company and site_id
. Jednym ze sposobów będzie użycie następującego kodu SQL wraz ze skryptem ( PHP
):
SELECT title, site_id, location, id, count( * )
FROM jobs
GROUP BY site_id, company, title, location
HAVING count( * ) >1
Po uruchomieniu tego zapytania mogę usunąć duplikaty za pomocą skryptu po stronie serwera.
Ale chcę wiedzieć, czy można to zrobić tylko za pomocą zapytania SQL.
mysql
sql
duplicates
Chetan
źródło
źródło
Odpowiedzi:
Bardzo łatwym sposobem na to jest dodanie
UNIQUE
indeksu do 3 kolumn. Podczas pisaniaALTER
instrukcji dołączIGNORE
słowo kluczowe. Tak jak:Spowoduje to usunięcie wszystkich zduplikowanych wierszy. Dodatkową korzyścią jest,
INSERTs
że przyszłe duplikaty będą błędne. Jak zawsze, możesz wykonać kopię zapasową przed uruchomieniem czegoś takiego ...źródło
set session old_alter_table=1;
Jeśli nie chcesz zmieniać właściwości kolumny, możesz użyć zapytania poniżej.
Ponieważ masz kolumnę, która ma unikalne identyfikatory (np.
auto_increment
Kolumny), możesz jej użyć do usunięcia duplikatów:W MySQL możesz to jeszcze bardziej uprościć dzięki operatorowi równości NULL-bezpieczne (inaczej „operatorowi statku kosmicznego” ):
źródło
MySQL ma ograniczenia dotyczące odwoływania się do tabeli, z której usuwasz. Możesz obejść ten problem przy tymczasowym stole, takim jak:
Z sugestii Kostanosa w komentarzach:
Jedyne wolne zapytanie powyżej to DELETE, w przypadkach, gdy masz bardzo dużą bazę danych. To zapytanie może być szybsze:
źródło
DELETE FROM YourTable USING YourTable, tmpTable WHERE YourTable.id=tmpTable.id
DELETE
, ale takżeINSERT
do tymczasowego stołu, zajęło mi to dużo czasu. Tak więc indeks tabeli tmp może bardzo pomóccreate index tmpTable_id_index on tmpTable (id)
, przynajmniej dla mnie.create temporary table tmpTable (id int, PRIMARY KEY (id));
Jeśli
IGNORE
instrukcja nie będzie działać tak jak w moim przypadku, możesz użyć poniższej instrukcji:źródło
Usuwanie duplikatów w tabelach MySQL jest częstym problemem, który ogólnie wynika z brakującego ograniczenia, aby uniknąć tych duplikatów przed ręką. Ale ten powszechny problem zwykle wiąże się z konkretnymi potrzebami ... które wymagają określonego podejścia. Podejście powinno być różne w zależności na przykład od wielkości danych, powielonego wpisu, który powinien być zachowany (zazwyczaj pierwszy lub ostatni), od tego, czy należy zachować indeksy, czy też chcemy wykonać dodatkowe działanie na zduplikowanych danych.
Istnieją również pewne specyficzne cechy samego MySQL, takie jak brak możliwości odwołania się do tej samej tabeli na podstawie FROM podczas wykonywania aktualizacji tabeli (spowoduje to błąd MySQL # 1093). Ograniczenie to można pokonać, używając wewnętrznego zapytania z tabelą tymczasową (jak sugerowano w niektórych podejściach powyżej). Ale to wewnętrzne zapytanie nie będzie szczególnie skuteczne w przypadku źródeł dużych zbiorów danych.
Istnieje jednak lepsze podejście do usuwania duplikatów, które jest zarówno wydajne, jak i niezawodne i można je łatwo dostosować do różnych potrzeb.
Ogólnym pomysłem jest utworzenie nowej tabeli tymczasowej, zwykle dodając unikalne ograniczenie, aby uniknąć dalszych duplikatów, i WSTAWIĆ dane z poprzedniej tabeli do nowej, jednocześnie dbając o duplikaty. Podejście to opiera się na prostych zapytaniach MySQL INSERT, tworzy nowe ograniczenie, aby uniknąć dalszych duplikatów, i pomija potrzebę stosowania wewnętrznego zapytania do wyszukiwania duplikatów i tabeli tymczasowej, którą należy przechowywać w pamięci (dopasowując również źródła dużych danych).
Tak można to osiągnąć. Biorąc pod uwagę, że mamy pracownika tabeli , z następującymi kolumnami:
Aby usunąć wiersze ze zduplikowaną kolumną ssn i zachować tylko pierwszy znaleziony wpis, można wykonać następujący proces:
Wyjaśnienie techniczne
⇒ Korzystając z tego podejścia, 1,6 mln rejestrów zostało przekonwertowanych na 6k w mniej niż 200s.
Chetan , postępując zgodnie z tym procesem, możesz szybko i łatwo usunąć wszystkie swoje duplikaty i utworzyć UNIKALNE ograniczenie, uruchamiając:
Oczywiście proces ten można dodatkowo zmodyfikować, aby dostosować go do różnych potrzeb podczas usuwania duplikatów. Oto kilka przykładów.
✔ Wariant dla zachowania ostatniego wpisu zamiast pierwszego
Czasami musimy zachować ostatni zduplikowany wpis zamiast pierwszego.
✔ Wariacja wykonywania niektórych zadań na duplikatach, na przykład utrzymywanie liczby znalezionych duplikatów
Czasami musimy wykonać dalsze przetwarzanie znalezionych duplikatów (na przykład rejestrowanie liczby duplikatów).
✔ Wariant regeneracji automatycznego pola przyrostowego id
Czasami używamy pola auto-inkrementalnego i, aby utrzymać możliwie jak najmniejszy indeks, możemy skorzystać z usunięcia duplikatów, aby zregenerować pole auto-inkrementalne w nowej tabeli tymczasowej.
✔ Dalsze warianty
Wiele dalszych modyfikacji jest również wykonalnych w zależności od pożądanego zachowania. Jako przykład, poniższe zapytania wykorzystają drugą tabelę tymczasową, aby oprócz 1) zachować ostatni wpis zamiast pierwszego; oraz 2) zwiększyć licznik znalezionych duplikatów; także 3) zregeneruj identyfikator pola auto-inkrementalnego, zachowując kolejność wpisów, tak jak w poprzednich danych.
źródło
Istnieje inne rozwiązanie:
źródło
jeśli masz duży stół z ogromną liczbą rekordów, powyższe rozwiązania nie będą działać lub zajmują zbyt dużo czasu. Mamy więc inne rozwiązanie
źródło
Mam ten fragment zapytania dla SQLServer, ale myślę, że można go używać w innych DBMS z niewielkimi zmianami:
Zapomniałem powiedzieć, że to zapytanie nie usuwa wiersza o najniższym identyfikatorze zduplikowanych wierszy. Jeśli to zadziała, wypróbuj to zapytanie:
źródło
ERROR 1093: You can't specify target table 'Table' for update in FROM clause
"You can't specify target table 'Table' for update in FROM..."
błąd, użyj:DELETE FROM Table WHERE Table.idTable IN ( SELECT MAX(idTable) FROM (SELECT * FROM idTable) AS tmp GROUP BY field1, field2, field3 HAVING COUNT(*) > 1)
co zmusza MySQL do utworzenia tabeli tymczasowej. Jednak w dużych zestawach danych jest bardzo wolny ... w takich przypadkach polecam kod Andomara, który jest znacznie szybszy.Szybszym sposobem jest wstawienie różnych wierszy do tabeli tymczasowej. Usunięcie duplikatów z tabeli zawierającej 8 milionów wierszy zajęło mi kilka godzin. Za pomocą wstawki i wyraźne zajęło to tylko 13 minut.
źródło
TRUNCATE TABLE tableName
a 5. linia powinna powiedziećINSERT INTO tableName SELECT * FROM tempTableName;
Rozwiązanie, które jest łatwe do zrozumienia i działa bez klucza podstawowego:
1) dodaj nową kolumnę logiczną
2) dodaj ograniczenie do zduplikowanych kolumn ORAZ nowej kolumny
3) ustaw kolumnę logiczną na true. To się powiedzie tylko w jednym ze zduplikowanych wierszy z powodu nowego ograniczenia
4) usuń wiersze, które nie zostały oznaczone jako Tokeep
5) upuść dodaną kolumnę
Sugeruję zachowanie dodanego ograniczenia, aby w przyszłości uniknąć nowych duplikatów.
źródło
Usuń zduplikowane wiersze za pomocą instrukcji DELETE JOIN MySQL udostępnia instrukcję DELETE JOIN, której możesz użyć do szybkiego usuwania zduplikowanych wierszy.
Poniższa instrukcja usuwa zduplikowane wiersze i zachowuje najwyższy identyfikator:
źródło
Znalazłem prosty sposób. (zachowaj najnowszą wersję)
źródło
Prosty i szybki dla wszystkich przypadków:
źródło
Spowoduje to usunięcie duplikatów wierszy o takich samych wartościach dla tytułu, firmy i witryny. Pierwsze wystąpienie zostanie zachowane, a pozostałe kopie zostaną usunięte
źródło
Odwiedzam tę stronę za każdym razem, gdy google „usuwam duplikaty z mysql”, ale dla moich rozwiązań THEIGNORE nie działają, ponieważ mam tabele mysql InnoDB
ten kod działa lepiej w dowolnym momencie
tableToclean = nazwa tabeli, którą musisz wyczyścić
tableToclean_temp = tymczasowa tabela utworzona i usunięta
źródło
To rozwiązanie przeniesie duplikaty do jednej tabeli, a unikaty do drugiej .
źródło
SELECT * FROM jobs GROUP BY site_id, company, title, location
?Począwszy od wersji 8.0 (2018), MySQL wreszcie obsługuje funkcje okien .
Funkcje okien są zarówno przydatne, jak i wydajne. Oto rozwiązanie, które pokazuje, jak ich użyć do rozwiązania tego zadania.
W podzapytaniu możemy użyć
ROW_NUMBER()
do przypisania pozycji do każdego rekordu w tabeli wcolumn1/column2
grupach, uporządkowanych wedługid
. Jeśli nie ma duplikatów, rekord otrzyma numer wiersza1
. Jeśli duplikat istnieje, zostaną one ponumerowane rosnącoid
(począwszy od1
).Po prawidłowym numerowaniu rekordów w podzapytaniu zewnętrzne zapytanie po prostu usuwa wszystkie rekordy, których numer wiersza nie jest równy 1.
Zapytanie:
źródło
Aby usunąć duplikat rekordu z tabeli.
lub
źródło
źródło
Aby zduplikować rekordy z unikatowymi kolumnami, np. COL1, COL2, COL3, nie należy replikować (załóżmy, że pominięto 3 unikatowe kolumny w strukturze tabeli i do tabeli wprowadzono wiele zduplikowanych wpisów)
Nadzieja pomoże dev.
źródło
TL; TR;
Dobrze opisany samouczek mający na celu rozwiązanie tego problemu można znaleźć na stronie mysqltutorial.org :
Jak usunąć zduplikowane wiersze w MySQL
Bardzo wyraźnie pokazano, jak usunąć duplikaty wierszy na trzy różne sposoby :
A) Za pomocą
DELETE JOIN
instrukcjiB) Korzystanie z tabeli pośredniej
C) Korzystanie z
ROW_NUMBER()
funkcjiMam nadzieję, że to komuś pomoże.
źródło
Mam tabelę, która zapomina dodać klucz podstawowy w wierszu identyfikatora. Chociaż ma identyfikator auto_increment na id. Ale pewnego dnia jedna rzecz odtworzy dziennik bin mysql w bazie danych, który wstawia zduplikowane wiersze.
Usuwam zduplikowany wiersz o
select T1.* from table_name T1 inner join (select count(*) as c,id from table_name group by id) T2 on T1.id = T2.id where T2.c > 1 group by T1.id;
usuń zduplikowane wiersze według identyfikatora
wstaw wiersz z wyeksportowanych danych.
Następnie dodaj klucz podstawowy do identyfikatora
źródło
Lubię dokładniej określać, które rekordy usuwam, więc oto moje rozwiązanie:
źródło
Możesz łatwo usunąć zduplikowane rekordy z tego kodu.
źródło
Musiałem to zrobić z polami tekstowymi i natrafiłem na limit 100 bajtów w indeksie.
Rozwiązałem to, dodając kolumnę, wykonując skrót pól md5 i wykonując alter.
źródło