Jaki jest najlepszy sposób na usunięcie zduplikowanych wierszy z dość dużej SQL Server
tabeli (tj. Ponad 300 000 wierszy)?
Wiersze oczywiście nie będą idealnymi duplikatami ze względu na istnienie RowID
pola tożsamości.
Mój stół
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
sql-server
tsql
duplicates
Seibar
źródło
źródło
DELETE FROM
bezpośrednio terminu CTE. Zobacz stackoverflow.com/q/18439054/398670ROWID()
funkcję kolumną RowID, jeśli istnieje)Odpowiedzi:
Zakładając, że nie ma wartości null, to
GROUP BY
unikalne kolumny i rowid jako rzędu zachować. Następnie po prostu usuń wszystko, co nie miało identyfikatora wiersza:SELECT
MIN (or MAX)
Jeśli masz identyfikator GUID zamiast liczby całkowitej, możesz go wymienić
z
źródło
DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
LEFT JOIN
jest mniej wydajny niżNOT EXISTS
sqlinthewild.co.za/index.php/2010/03/23/... Ta sama strona porównuje równieżNOT IN
zNOT EXISTS
. sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in Spośród 3, moim zdaniem,NOT EXISTS
działa najlepiej. Wszystkie trzy wygenerują plan z samozłączeniem, którego można jednak uniknąć.DELETE MyTable FROM MyTable
poprawna składnia? Nie widzę umieszczania nazwy tabeli zaraz po opcjiDELETE
jako opcji w dokumentacji tutaj . Przepraszam, jeśli jest to oczywiste dla innych; Jestem początkującym w SQL tylko próbuję się uczyć. Co ważniejsze niż dlaczego to działa: jaka jest różnica między podaniem nazwy tabeli, czy nie?Innym możliwym sposobem na to jest
Używam
ORDER BY (SELECT 0)
powyższego, ponieważ jest to dowolny wiersz, który należy zachować w przypadku remisu.Aby zachować najnowszą
RowID
, na przykład możesz użyćORDER BY RowID DESC
Plany wykonania
Plan wykonania tego jest często prostszy i wydajniejszy niż w przyjętej odpowiedzi, ponieważ nie wymaga samodzielnego dołączenia.
Jednak nie zawsze tak jest. Jednym z miejsc, w których
GROUP BY
rozwiązanie może być preferowane, są sytuacje, w których agregat skrótu byłby wybierany zamiast agregatu strumienia.ROW_NUMBER
Rozwiązanie będzie zawsze daje dość dużo ten sam plan, podczas gdyGROUP BY
strategia jest bardziej elastyczny.Czynniki, które mogą sprzyjać podejściu agregacji skrótów, to:
W skrajnych wersjach tego drugiego przypadku (jeśli jest bardzo niewiele grup z wieloma duplikatami w każdej), można również rozważyć wstawienie wierszy w celu zachowania w nowej tabeli, a następnie
TRUNCATE
skopiowanie oryginału i skopiowanie ich z powrotem, aby zminimalizować rejestrowanie w porównaniu do usunięcia bardzo duża część rzędów.źródło
uniqueidentifier
. Ten jest o wiele prostszy i działa idealnie na każdym stole. Dzięki Martin.RowId
) do porównania.W witrynie pomocy technicznej Microsoft znajduje się dobry artykuł na temat usuwania duplikatów . To dość konserwatywne - każą ci robić wszystko w osobnych krokach - ale powinno dobrze działać na dużych stołach.
W przeszłości korzystałem z autozłączeń, chociaż prawdopodobnie można to zrobić z klauzulą HAVING:
źródło
Poniższe zapytanie jest przydatne do usunięcia zduplikowanych wierszy. Tabela w tym przykładzie ma
ID
jako kolumnę tożsamości, a kolumny ze zduplikowanymi danymi toColumn1
,Column2
iColumn3
.Wykorzystanie Poniżej przedstawiono scenariusz
GROUP BY
,HAVING
,ORDER BY
w jednym zapytaniu i zwraca wyniki z duplikatu kolumny i jej liczenia.źródło
NOT IN
często działa lepiej niżOUTER JOIN ... NULL
. DodałbymHAVING MAX(ID) IS NOT NULL
do zapytania, chociaż chociaż semantycznie nie powinno to być konieczne, ponieważ może to poprawić przykładPostgres:
źródło
źródło
Spowoduje to usunięcie duplikatów wierszy, z wyjątkiem pierwszego wiersza
Patrz ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )
źródło
Wolę CTE do usuwania duplikatów wierszy z tabeli serwera SQL
zdecydowanie zalecamy śledzenie tego artykułu :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/
źródło
Aby pobrać zduplikowane wiersze:
Aby usunąć zduplikowane wiersze:
źródło
DELETE FROM
, po drugie, nie będzie działać, ponieważ nie możeszSELECT
z tej samej tabeli, z którejDELETE
pochodzi. W MySQL to się zaczynaMySQL error 1093
.Szybkie i brudne, aby usunąć dokładnie zduplikowane wiersze (dla małych tabel):
źródło
Wolę podzapytanie \ posiadające liczbę (*)> 1 rozwiązania dla złączenia wewnętrznego, ponieważ łatwiej mi było czytać i bardzo łatwo było zmienić instrukcję SELECT, aby sprawdzić, co zostanie usunięte przed uruchomieniem.
źródło
MAX(id)
wyeliminować te ostatnie duplikaty, i dodałemLIMIT 1000000
do wewnętrznego zapytania, aby nie musiało skanować całej tabeli. To pokazało postęp znacznie szybciej niż inne odpowiedzi, które wydawałyby się zawieszone przez wiele godzin. Po przycięciu tabeli do możliwego do zarządzania rozmiaru, możesz zakończyć inne zapytania. Wskazówka: upewnij się, że col1 / col2 / col3 ma wskaźniki dla grup według.źródło
Myślałem, że podzielę się moim rozwiązaniem, ponieważ działa w szczególnych okolicznościach. W moim przypadku tabela ze zduplikowanymi wartościami nie miała klucza obcego (ponieważ wartości zostały zduplikowane z innej bazy danych).
PS: pracując nad takimi rzeczami zawsze korzystam z transakcji, nie tylko zapewnia to, że wszystko jest wykonywane jako całość, ale pozwala mi także na testowanie bez ryzyka. Ale oczywiście powinieneś zrobić kopię zapasową, aby się upewnić ...
źródło
To zapytanie pokazało mi bardzo dobrą wydajność:
usunął 1 mln wierszy w nieco ponad 30 sekund z tabeli 2 mln (50% duplikatów)
źródło
Korzystanie z CTE. Chodzi o to, aby dołączyć do jednej lub więcej kolumn, które tworzą zduplikowany rekord, a następnie usunąć dowolne:
źródło
Jeszcze jedno łatwe rozwiązanie można znaleźć pod linkiem wklejonym tutaj . Ten jest łatwy do uchwycenia i wydaje się być skuteczny w przypadku większości podobnych problemów. Dotyczy to jednak SQL Server, ale zastosowana koncepcja jest więcej niż akceptowalna.
Oto odpowiednie fragmenty z połączonej strony:
Rozważ te dane:
Jak więc usunąć te zduplikowane dane?
Najpierw wstaw kolumnę tożsamości do tej tabeli przy użyciu następującego kodu:
Użyj następującego kodu, aby go rozwiązać:
źródło
ROW_NUMBER
Wersja działa dobrze w tym przypadku bez konieczności przechodzenia do dodawania nowej kolumny przed rozpoczęciem.Oto kolejny dobry artykuł na temat usuwania duplikatów .
Omówiono, dlaczego trudno: „ SQL opiera się na algebrze relacyjnej, a duplikaty nie mogą występować w algebrze relacyjnej, ponieważ duplikaty nie są dozwolone w zestawie ”.
Rozwiązanie tabeli temp i dwa przykłady mysql.
W przyszłości zamierzasz temu zapobiec na poziomie bazy danych lub z perspektywy aplikacji. Sugerowałbym poziom bazy danych, ponieważ twoja baza danych powinna być odpowiedzialna za utrzymanie integralności referencyjnej, programiści po prostu powodują problemy;)
źródło
Oh, pewnie. Użyj tabeli temp. Jeśli potrzebujesz pojedynczej, mało wydajnej instrukcji, która „działa”, możesz użyć:
Zasadniczo dla każdego wiersza w tabeli wybór podrzędny znajduje górny identyfikator wiersza wszystkich wierszy, które są dokładnie takie same jak rozważany wiersz. W rezultacie otrzymujesz listę RowID, które reprezentują „oryginalne” niepowielone wiersze.
źródło
Miałem tabelę, w której musiałem zachować niepowielone wiersze. Nie jestem pewien szybkości ani wydajności.
źródło
HAVING COUNT(*) > 1
?Użyj tego
źródło
Innym sposobem jest utworzenie nowej tabeli z tymi samymi polami i unikalnym indeksem . Następnie przenieś wszystkie dane ze starej tabeli do nowej tabeli . Automatycznie ignoruj SQL SERVER (istnieje również opcja, co zrobić, jeśli pojawi się zduplikowana wartość: zignoruj, przerwij lub sth) zduplikowane wartości. Mamy więc tę samą tabelę bez zduplikowanych wierszy. Jeśli nie chcesz Unique Index, po przesłaniu danych możesz go upuścić .
Szczególnie w przypadku większych tabel możesz użyć DTS (pakiet SSIS do importu / eksportu danych), aby szybko przenieść wszystkie dane do nowej tabeli o unikalnym indeksowaniu. W przypadku 7 milionów wierszy zajmuje to tylko kilka minut.
źródło
Korzystając z poniższego zapytania, możemy usunąć zduplikowane rekordy na podstawie pojedynczej kolumny lub wielu kolumn. poniższe zapytanie jest usuwane na podstawie dwóch kolumn. nazwa tabeli to:
testing
i nazwy kolumnempno,empname
źródło
Utwórz nowy pusty stół o tej samej strukturze
Wykonaj zapytanie w ten sposób
Następnie wykonaj to zapytanie
źródło
Jest to najprostszy sposób na usunięcie duplikatu rekordu
http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105
źródło
Chciałbym wspomnieć o tym podejściu, ponieważ może być pomocne i działa na wszystkich serwerach SQL: Bardzo często jest tylko jeden - dwa duplikaty, a identyfikatory i liczba duplikatów są znane. W tym przypadku:
źródło
Nie wiem, jak dobrze by to działało, ale myślę, że możesz napisać wyzwalacz, aby to wymusić, nawet jeśli nie możesz tego zrobić bezpośrednio za pomocą indeksu. Coś jak:
Ponadto, varchar (2048) brzmi dla mnie podejrzanie (niektóre rzeczy w życiu to 2048 bajtów, ale jest to dość rzadkie); czy to naprawdę nie powinno być varchar (max)?
źródło
Kolejny sposób to zrobić:
źródło
źródło
źródło
Chcę wyświetlić podgląd wierszy, które chcesz usunąć, i zachowaj kontrolę nad tym, który z duplikatów chcesz zachować. Zobacz http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/
źródło