Mam tabelę z kolumną varchar i chciałbym znaleźć wszystkie rekordy, które mają zduplikowane wartości w tej kolumnie. Jakiego zapytania najlepiej użyć do znalezienia duplikatów?
Ale w jaki sposób jest to przydatne, jeśli nie można uzyskać identyfikatorów wierszy ze zduplikowanymi wartościami? Tak, możesz wykonać nowe zapytanie pasujące do każdej zduplikowanej wartości, ale czy można po prostu podać listę duplikatów?
NobleUplift
23
@NobleUplift Możesz to zrobić, GROUP_CONCAT(id)a wyświetli się lista identyfikatorów. Zobacz moją odpowiedź na przykład.
Matt Rardon
5
Co by to znaczyło, gdyby powiedział ERROR: column "c" does not exist LINE 1?
Użytkownik
15
Jestem zdezorientowany, dlaczego jest to zaakceptowana odpowiedź i dlaczego ma tak wiele pozytywnych opinii. OP zapytał: „Chciałbym znaleźć wszystkie rekordy, które mają zduplikowane wartości w tej kolumnie”. Ta odpowiedź zwraca tabelę zliczeń. -1
Monica Heddneck
4
Dla tych, którzy nie rozumieją, jak działa HAVING - jest to po prostu filtr zestawu wyników, więc dzieje się to po głównym zapytaniu.
John Hunt
236
SELECT varchar_col
FROMtableGROUPBY varchar_col
HAVING COUNT(*)>1;
Lepsza niż odpowiedź @ levik, ponieważ nie dodaje dodatkowej kolumny. Sprawia, że jest użyteczny w połączeniu z IN()/ NOT IN().
wmassingham
172
SELECT*FROM mytable mto
WHEREEXISTS(SELECT1FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1,1)
To zapytanie zwraca pełne rekordy, a nie tylko odrębne varchar_column.
To zapytanie nie używa COUNT(*). Jeśli jest wiele duplikatów, COUNT(*)jest kosztowne i nie potrzebujesz całości COUNT(*), musisz tylko wiedzieć, czy są dwa wiersze o tej samej wartości.
Posiadanie indeksu varchar_columnprzyspieszy oczywiście to zapytanie.
Bardzo dobre. Dodałem ORDER BY varchar_column DESCna końcu zapytania.
trante
8
To powinien być zaakceptowany odpowiedź, jak GROUP BYi HAVINGpowraca tylko jeden z możliwych duplikatów. Ponadto wydajność z polem indeksowanym zamiast COUNT(*)oraz możliwość ORDER BYgrupowania zduplikowanych rekordów.
Rémi Breton,
1
Jak stwierdzono w powyższych komentarzach, to zapytanie pozwala wyświetlić listę wszystkich zduplikowanych wierszy. Bardzo przydatne.
TryHarder
4
Patrząc na to, nie rozumiem, jak by to działało. Czy wewnętrzny warunek nie zawsze będzie prawdziwy, ponieważ jakikolwiek rząd w zewnętrznym stole będzie również dostępny w wewnętrznym stole, a więc każdy rząd zawsze będzie przynajmniej taki sam? Próbowałem zapytania i uzyskałem wynik, który podejrzewałem - zwracany był każdy wiersz. Ale przy tak wielu pozytywnych opiniach wątpię w siebie. Czy w wewnętrznym zapytaniu brakuje czegoś takiego jak „AND mto.id <> mti.id”? Gdy to dodam, działa dla mnie.
Clox,
2
@Quassnoi W porządku. Próbowałem umieścić go na sqlfiddle, ale poddałem się, ponieważ każde zapytanie, które próbuję uruchomić, oprócz tworzenia schematu, wygasło. Doszedłem do wniosku, że samo usunięcie „EXISTS” sprawia, że zapytanie działa dla mnie poprawnie.
Clox
144
Opierając się na odpowiedzi Levika, aby uzyskać identyfikatory zduplikowanych wierszy, możesz zrobić a, GROUP_CONCATjeśli Twój serwer to obsługuje (zwróci listę identyfikatorów oddzielonych przecinkami).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUPBY name HAVING c >1;
Cały czas nie wiedząc o GROUP_CONCAT ()! bardzo, bardzo przydatne.
aesede
Naprawdę doceniany Matt. To jest naprawdę pomocne! Dla tych, którzy próbują zaktualizować w phpmyadmin, jeśli zostawisz identyfikator razem z funkcją w ten sposób: SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]umożliwia on edycję bezpośrednią i powinien zaktualizować wszystkie zaangażowane wiersze (lub przynajmniej pierwszy dopasowany), ale niestety edycja generuje błąd JavaScript. ..
Armfoot
Jak byś wtedy obliczył, ile identyfikatorów podlega duplikacji?
CMCDragonkai
2
Jak mogę nie zgrupować wszystkich identyfikatorów, ale zamiast tego wymienić je od pierwszego do ostatniego; ze wszystkimi odpowiednimi wartościami w kolumnach obok nich? Zamiast grupować, pokazuje tylko ID 1 i jego wartość, ID 2 i jego wartość. NAWET, jeśli wartości identyfikatora są takie same.
MailBlade,
1
Niezwykle pomocna odpowiedź, powinna być na górze, aby więcej osób ją zobaczyło. Pamiętam, jak wiele bólu przeżyłem, tworząc takie listy, i było ono dostępne przez cały czas jako polecenie.
John
13
Zakładając, że twoja tabela ma nazwę TableABC, a kolumna, którą chcesz, to Col, a klucz podstawowy do T1 to Key.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key<> b.Key
Przewagą tego podejścia nad powyższą odpowiedzią jest to, że daje on Klucz.
+1 Ponieważ jest to przydatne. Chociaż, jak na ironię, sam wynik zawiera duplikaty (wymienia aib, a następnie
bib
2
@FabienSnauwaert Możesz pozbyć się niektórych duplikatów, porównując mniej niż (lub więcej niż)
Michael
@TechTravel Pomyśl, że twoja odpowiedź jest bardzo jasna, dziękuję za to, ale na dużym stole zajmuje to trochę czasu (około 2 mln na więcej 20 000 wpisów w tabeli), a po pokazaniu 25 pierwszych wyników, jeśli kliknę, aby wyświetlić następny, phpmyadmin pokaż błąd "# 1052 - Kolumna „id” w klauzuli kolejności jest niejednoznaczna ”
bcag2
12
SELECT*FROM`dps`WHERE pid IN(SELECT pid FROM`dps`GROUPBY pid HAVING COUNT(pid)>1)
Nie, ponieważ jest to prawdopodobnie najwolniejszy z całej serii. Podselekcje są notorycznie wolne, ponieważ są wykonywane dla każdego zwracanego wiersza.
Oddman
10
Aby dowiedzieć się, ile rekordów jest duplikatami w kolumnie z nazwami w Pracowniku, pomocne jest poniższe zapytanie;
Select name from employee groupby name having count(*)>1;
FYI - Będziesz chciał „wybrać wyraźne somecol ..”, jeśli istnieje możliwość istnienia więcej niż 1 zduplikowanego rekordu, w przeciwnym razie wyniki będą zawierać duplikaty znalezionych duplikatów.
Drew
7
SELECT t.*,(select count(*)from city as tt
where tt.name=t.name)as count
FROM`city`as t
where(select count(*)from city as tt
where tt.name=t.name
)>1orderby count desc
Zastąp miasto swoim stołem. Zastąp nazwę swoją nazwą pola
Biorąc dalej odpowiedź @ maxyfc , musiałem znaleźć wszystkie wiersze, które zostały zwrócone ze zduplikowanymi wartościami, aby móc je edytować w MySQL Workbench :
SELECT*FROMtableWHERE field IN(SELECT field FROMtableGROUPBY field HAVING count(*)>1)ORDERBY field
Widziałem powyższy wynik i zapytanie będzie działać poprawnie, jeśli chcesz sprawdzić wartość jednej kolumny, która jest zduplikowana. Na przykład e-mail.
Ale jeśli musisz sprawdzić więcej kolumn i chcesz sprawdzić kombinację wyniku, aby zapytanie działało poprawnie:
SELECT COUNT(CONCAT(name,email))AS tot,
name,
email
FROM users
GROUPBY CONCAT(name,email)HAVING tot>1(This query will SHOW the USER list which ARE greater THAN 1AND also COUNT)
Dokładnie to, co było potrzebne! Oto moje zapytanie, sprawdzanie 3 pól pod kątem duplikatów:SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Kai Noack
4
Wolę używać funkcji okienkowych (MySQL 8.0+) do znajdowania duplikatów, ponieważ widziałem cały wiersz:
WITH cte AS(SELECT*,COUNT(*)OVER(PARTITIONBY col_name)AS num_of_duplicates_group
,ROW_NUMBER()OVER(PARTITIONBY col_name ORDERBY col_name2)AS pos_in_group
FROMtable)SELECT*FROM cte
WHERE num_of_duplicates_group >1;
SELECT
t.*,(SELECT COUNT(*)FROM city AS tt WHERE tt.name=t.name)AS count
FROM`city`AS t
WHERE(SELECT count(*)FROM city AS tt WHERE tt.name=t.name)>1ORDERBY count DESC
Warto zauważyć, że jest to nieznośnie powolne lub może nawet nie zakończyć się, jeśli kolumna, o którą pytamy, nie jest indeksowana. W przeciwnym razie, byłem w stanie zmienić a.emailsię a.*i uzyskać wszystkie identyfikatory wierszy z duplikatów.
NobleUplift
@NobleUplift O czym ty mówisz?
Michael
@Michael Cóż, ponieważ ma on trzy lata, nie mogę przetestować jakiejkolwiek wersji MySQL, której używałem, ale próbowałem tego samego zapytania w bazie danych, w której wybrana kolumna nie miała indeksu, więc zajęło mi to sporo kilka sekund do końca. Zmiana na SELECT DISTINCT a.*prawie natychmiastowa.
NobleUplift,
@NobleUplift Ah ok. Rozumiem, że jest powolny ... martwi mnie to, że „może nawet nie skończyć”.
Michael
@Michael Nie pamiętam, na której tabeli w naszym systemie musiałem uruchomić tę kwerendę, ale dla tych z kilkoma milionami rekordów prawdopodobnie by się skończyły, ale w czasie, który trwał tak długo, że przestałem patrzeć, kiedy faktycznie by się skończyło.
NobleUplift,
1
Aby usunąć zduplikowane wiersze z wieloma polami, najpierw anuluj je do nowego unikalnego klucza określonego dla jedynych odrębnych wierszy, a następnie użyj polecenia „grupuj”, aby usunąć zduplikowane wiersze z tym samym nowym unikalnym kluczem:
Create TEMPORARY table tmp select concat(f1,f2)as cfs,t1.*from mytable as t1;Createindex x_tmp_cfs on tmp(cfs);Createtable unduptable select f1,f2,...from tmp groupby cfs;
Jeden bardzo spóźniony wkład ... na wypadek, gdyby to pomogło każdemu zejść w dół linii ... Miałem zadanie znaleźć pasujące pary transakcji (właściwie obie strony przelewów między rachunkami) w aplikacji bankowej, aby zidentyfikować, które z nich były „z” i „do” dla każdej transakcji przeniesienia między kontami, więc skończyliśmy na tym:
SELECT
LEAST(primaryid, secondaryid)AS transactionid1,
GREATEST(primaryid, secondaryid)AS transactionid2
FROM(SELECT table1.transactionid AS primaryid,
table2.transactionid AS secondaryid
FROM financial_transactions table1
INNERJOIN financial_transactions table2
ON table1.accountid = table2.accountid
AND table1.transactionid <> table2.transactionid
AND table1.transactiondate = table2.transactiondate
AND table1.sourceref = table2.destinationref
AND table1.amount =(0- table2.amount))AS DuplicateResultsTable
GROUPBY transactionid1
ORDERBY transactionid1;
W rezultacie DuplicateResultsTablewiersze zawierające pasujące (tj. Zduplikowane) transakcje zapewniają również te same identyfikatory transakcji w odwrotnej kolejności za drugim razem, gdy dopasowuje tę samą parę, więc element zewnętrzny SELECTmoże grupować według pierwszego identyfikatora transakcji, który jest wykonywany za pomocą LEASTi, GREATESTaby upewnić się, że dwa transakcje są zawsze w tej samej kolejności w wynikach, dzięki czemu jest bezpieczny GROUPprzez pierwszy, eliminując w ten sposób wszystkie duplikaty dopasowań. Przejrzał prawie milion rekordów i zidentyfikował ponad 12 000 meczów w niecałe 2 sekundy. Oczywiście transakcja jest głównym indeksem, który naprawdę pomógł.
Odpowiedzi:
Zrób
SELECT
zGROUP BY
klauzulą. Powiedzmy, że nazwa to kolumna, w której chcesz znaleźć duplikaty:Zwróci to wynik z wartością nazwy w pierwszej kolumnie i liczbą wyświetleń tej wartości w drugiej kolumnie.
źródło
GROUP_CONCAT(id)
a wyświetli się lista identyfikatorów. Zobacz moją odpowiedź na przykład.ERROR: column "c" does not exist LINE 1
?źródło
IN()
/NOT IN()
.To zapytanie zwraca pełne rekordy, a nie tylko odrębne
varchar_column
.To zapytanie nie używa
COUNT(*)
. Jeśli jest wiele duplikatów,COUNT(*)
jest kosztowne i nie potrzebujesz całościCOUNT(*)
, musisz tylko wiedzieć, czy są dwa wiersze o tej samej wartości.Posiadanie indeksu
varchar_column
przyspieszy oczywiście to zapytanie.źródło
ORDER BY varchar_column DESC
na końcu zapytania.GROUP BY
iHAVING
powraca tylko jeden z możliwych duplikatów. Ponadto wydajność z polem indeksowanym zamiastCOUNT(*)
oraz możliwośćORDER BY
grupowania zduplikowanych rekordów.Opierając się na odpowiedzi Levika, aby uzyskać identyfikatory zduplikowanych wierszy, możesz zrobić a,
GROUP_CONCAT
jeśli Twój serwer to obsługuje (zwróci listę identyfikatorów oddzielonych przecinkami).źródło
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
umożliwia on edycję bezpośrednią i powinien zaktualizować wszystkie zaangażowane wiersze (lub przynajmniej pierwszy dopasowany), ale niestety edycja generuje błąd JavaScript. ..Zakładając, że twoja tabela ma nazwę TableABC, a kolumna, którą chcesz, to Col, a klucz podstawowy do T1 to Key.
Przewagą tego podejścia nad powyższą odpowiedzią jest to, że daje on Klucz.
źródło
źródło
Aby dowiedzieć się, ile rekordów jest duplikatami w kolumnie z nazwami w Pracowniku, pomocne jest poniższe zapytanie;
źródło
aby uzyskać wszystkie dane, które zawierają duplikację, użyłem tego:
TableName = tabela, z którą pracujesz.
DupliactedData = zduplikowane dane, których szukasz.
źródło
Moje ostatnie zapytanie zawierało kilka odpowiedzi, które pomogły - łączenie grupy według, liczenia i GROUP_CONCAT.
Podaje to identyfikator obu przykładów (oddzielonych przecinkami), potrzebny kod kreskowy i liczbę duplikatów.
Zmień odpowiednio tabelę i kolumny.
źródło
Nie widzę żadnych podejść do JOIN, które mają wiele zastosowań pod względem duplikatów.
Takie podejście daje rzeczywiste podwojone wyniki.
źródło
Zastąp miasto swoim stołem. Zastąp nazwę swoją nazwą pola
źródło
Biorąc dalej odpowiedź @ maxyfc , musiałem znaleźć wszystkie wiersze, które zostały zwrócone ze zduplikowanymi wartościami, aby móc je edytować w MySQL Workbench :
źródło
Widziałem powyższy wynik i zapytanie będzie działać poprawnie, jeśli chcesz sprawdzić wartość jednej kolumny, która jest zduplikowana. Na przykład e-mail.
Ale jeśli musisz sprawdzić więcej kolumn i chcesz sprawdzić kombinację wyniku, aby zapytanie działało poprawnie:
źródło
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Wolę używać funkcji okienkowych (MySQL 8.0+) do znajdowania duplikatów, ponieważ widziałem cały wiersz:
DB Fiddle Demo
źródło
źródło
Poniżej znajdziesz wszystkie id_produktu, które są używane więcej niż jeden raz. Otrzymujesz tylko jeden rekord dla każdego id_produktu.
Kod pochodzi z: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
źródło
źródło
źródło
a.email
sięa.*
i uzyskać wszystkie identyfikatory wierszy z duplikatów.SELECT DISTINCT a.*
prawie natychmiastowa.Aby usunąć zduplikowane wiersze z wieloma polami, najpierw anuluj je do nowego unikalnego klucza określonego dla jedynych odrębnych wierszy, a następnie użyj polecenia „grupuj”, aby usunąć zduplikowane wiersze z tym samym nowym unikalnym kluczem:
źródło
CREATE TEMPORARY TABLE ...
? Świetne byłoby krótkie wyjaśnienie twojego rozwiązania.Jeden bardzo spóźniony wkład ... na wypadek, gdyby to pomogło każdemu zejść w dół linii ... Miałem zadanie znaleźć pasujące pary transakcji (właściwie obie strony przelewów między rachunkami) w aplikacji bankowej, aby zidentyfikować, które z nich były „z” i „do” dla każdej transakcji przeniesienia między kontami, więc skończyliśmy na tym:
W rezultacie
DuplicateResultsTable
wiersze zawierające pasujące (tj. Zduplikowane) transakcje zapewniają również te same identyfikatory transakcji w odwrotnej kolejności za drugim razem, gdy dopasowuje tę samą parę, więc element zewnętrznySELECT
może grupować według pierwszego identyfikatora transakcji, który jest wykonywany za pomocąLEAST
i,GREATEST
aby upewnić się, że dwa transakcje są zawsze w tej samej kolejności w wynikach, dzięki czemu jest bezpiecznyGROUP
przez pierwszy, eliminując w ten sposób wszystkie duplikaty dopasowań. Przejrzał prawie milion rekordów i zidentyfikował ponad 12 000 meczów w niecałe 2 sekundy. Oczywiście transakcja jest głównym indeksem, który naprawdę pomógł.źródło
źródło
źródło
Jeśli chcesz usunąć zduplikowane użycie
DISTINCT
W przeciwnym razie użyj tego zapytania:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
źródło
Spróbuj użyć tego zapytania:
źródło