Znajdź duplikaty rekordów w MySQL

Chcę wyciągnąć duplikaty rekordów w bazie danych MySQL. Można to zrobić za pomocą:

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

Co daje:

100 MAIN ST    2

Chciałbym wyciągnąć go tak, że pokazuje każdy wiersz, który jest duplikatem. Coś w stylu:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST
Jakieś pomysły, jak to zrobić? Staram się unikać robienia pierwszego, a następnie przeglądania duplikatów z drugim zapytaniem w kodzie.
Author: Chris Bartow, 2009-05-12

23 answers

Kluczem jest przepisanie tego zapytania tak, aby mogło być użyte jako zapytanie podrzędne.

SELECT firstname, 
   lastname, 
   list.address 
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;
 701
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 20:35:36
SELECT date FROM logs group by date having count(*) >= 2
 367
Author: trt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-19 23:24:14

Dlaczego po prostu nie połączyć tabeli z samym sobą?

SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

DISTINCT jest potrzebny, jeśli adres może istnieć więcej niż dwa razy.

 199
Author: rudolfson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-21 07:54:52

Próbowałem najlepszej odpowiedzi wybranej na to pytanie, ale trochę mnie to zdezorientowało. Potrzebowałem tego tylko na jednym polu z mojego stołu. Poniższy przykład z TEN link zadziałał dla mnie bardzo dobrze:

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;
 59
Author: Arman Malik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-20 19:17:36
select `cityname` from `codcities` group by `cityname` having count(*)>=2

To jest podobne Zapytanie, o które prosiłeś, a jego 200% działa i jest łatwe. Smacznego!!!

 47
Author: pratswinz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-06 05:33:15

Czy to nie jest łatwiejsze:

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1

?

 45
Author: Tudor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-01 12:37:57

Znajdź zduplikowanych użytkowników przez adres e-mail z tym zapytaniem...

SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;
 37
Author: doublejosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-12 04:26:26

Możemy znaleźć duplikaty również na więcej niż jednym polu.W takich przypadkach możesz użyć poniższego formatu.

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;
 20
Author: KESAVAN PURUSOTHAMAN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-17 21:05:46

Innym rozwiązaniem byłoby użycie aliasów tabel, w ten sposób:

SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

Wszystko, co naprawdę robisz w tym przypadku, to pobranie oryginalnejlisty tabeli, utworzenie dwóchp retend tabel -- p1 oraz p2 -- z tego, a następnie wykonanie join w kolumnie adresu(linia 3). 4. linia zapewnia, że ten sam rekord nie pojawia się wiele razy w zestawie wyników ("duplicate duplicates").

 13
Author: jerdiggity,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-14 04:14:30

Znajdowanie duplikatów adresów jest znacznie bardziej skomplikowane, niż się wydaje, zwłaszcza jeśli wymaga się dokładności. Zapytanie MySQL nie wystarczy w tym przypadku...

Pracuję w SmartyStreets , gdzie zajmujemy się walidacją, duplikacją i innymi rzeczami, i widziałem wiele różnych wyzwań z podobnymi problemami.

Istnieje kilka usług stron trzecich, które oznaczą duplikaty na liście dla Ciebie. Robienie tego wyłącznie z subquery MySQL nie będzie rozliczać różnice w formatach adresów i standardach. USPS (dla adresu USA) ma pewne wytyczne, aby wprowadzić te standardy, ale tylko garstka dostawców jest certyfikowana do wykonywania takich operacji.

Zalecałbym więc, aby najlepszą odpowiedzią było wyeksportowanie tabeli do pliku CSV i przesłanie jej do zdolnego procesora list. Jednym z nich jest LiveAddress , który automatycznie zrobi to za Ciebie w ciągu kilku sekund do kilku minut. Będzie oznaczał zduplikowane wiersze nowym pole o nazwie "Duplicate" i w nim wartość Y.

 12
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-27 10:46:16

Nie będzie zbyt wydajny, ale powinien działać:

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;
 10
Author: Chad Birch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 18:28:47

Spowoduje wybranie duplikatów w jednym przejściu tabeli, bez zapytań podrzędnych.

SELECT  *
FROM    (
        SELECT  ao.*, (@r := @r + 1) AS rn
        FROM    (
                SELECT  @_address := 'N'
                ) vars,
                (
                SELECT  *
                FROM
                        list a
                ORDER BY
                        address, id
                ) ao
        WHERE   CASE WHEN @_address <> address THEN @r := 0 ELSE 0 END IS NOT NULL
                AND (@_address := address ) IS NOT NULL
        ) aoo
WHERE   rn > 1

To zapytanie emuluje ROW_NUMBER() obecne w Oracle i SQL Server

Zobacz artykuł na moim blogu po szczegóły:

 10
Author: Quassnoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 18:36:31

To również pokaże Ci, ile duplikatów ma i uporządkuje wyniki bez łączenia

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC
 8
Author: Martin Tonev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-17 10:28:46
 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)
 4
Author: Ryan Roper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 06:36:20
select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

Dla Twojego stołu byłoby to coś w stylu

select * from list l1 inner join (select distinct address from list as list2)l2 where l1.address=l2.address

To zapytanie wyświetli wszystkie odrębne wpisy adresowe w tabeli listy... Nie jestem pewien, jak to będzie działać, jeśli masz jakieś podstawowe wartości klucza dla name, itp..

 4
Author: Neha Patil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-01 12:31:20

Najszybsza procedura usuwania duplikatów:

/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;
 4
Author: venkatesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-15 04:49:15

Osobiście to zapytanie rozwiązało mój problem:

SELECT `SUB_ID`, COUNT(SRV_KW_ID) as subscriptions FROM `SUB_SUBSCR` group by SUB_ID, SRV_KW_ID HAVING subscriptions > 1;

Skrypt pokazuje wszystkie identyfikatory Abonenta, które istnieją więcej niż jeden raz w tabeli oraz liczbę znalezionych duplikatów.

Oto kolumny tabeli:

| SUB_SUBSCR_ID | int(11)     | NO   | PRI | NULL    | auto_increment |
| MSI_ALIAS     | varchar(64) | YES  | UNI | NULL    |                |
| SUB_ID        | int(11)     | NO   | MUL | NULL    |                |    
| SRV_KW_ID     | int(11)     | NO   | MUL | NULL    |                |

Nadzieję, że będzie to pomocne dla ciebie albo!

 4
Author: Ionut Petre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-12 10:22:45
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) > 1 order by count desc

Zastąp Miasto swoją tabelą. Zastąp nazwę nazwą pola

 3
Author: Lalit Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-25 05:56:53
    SELECT *
    FROM (SELECT  address, COUNT(id) AS cnt
    FROM list
    GROUP BY address
    HAVING ( COUNT(id) > 1 ))
 2
Author: DJ.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 06:36:30
    Find duplicate Records:

    Suppose we have table : Student 
    student_id int
    student_name varchar
    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

    Now we want to see duplicate records
    Use this query:


   select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;

+--------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+
 1
Author: Usman Yaqoob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-09 07:36:42

Aby szybko zobaczyć zduplikowane wiersze, możesz uruchomić jedno proste zapytanie

Tutaj sprawdzam tabelę i wypisuję wszystkie zduplikowane wiersze z tym samym user_id, market_place i sku:

select user_id, market_place,sku, count(id)as totals from sku_analytics group by user_id, market_place,sku having count(id)>1;

Aby usunąć zduplikowany wiersz, musisz zdecydować, który wiersz chcesz usunąć. Np. ten z niższym id (Zwykle starszy) lub może jakieś inne informacje o dacie. W moim przypadku chcę tylko usunąć niższy identyfikator, ponieważ nowszy IDENTYFIKATOR to najnowsze informacje.

Najpierw sprawdź, czy prawo zapisy zostaną usunięte. Tutaj wybieram rekord wśród duplikatów, który zostanie usunięty (przez unikalny identyfikator).

select a.user_id, a.market_place,a.sku from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

Następnie uruchamiam zapytanie delete, aby usunąć dupki:

delete a from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

Backup, Double check, verify, verify backup then execute.

 0
Author: Ganesh Krishnan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-06 20:32:36

select address from list where address = any (select address from (select address, count(id) cnt from list group by address having cnt > 1 ) as t1) order by address

Wewnętrzne zapytanie podrzędne zwraca wiersze o zduplikowanym adresie, a następnie zewnętrzne zapytanie podrzędne zwraca kolumnę address dla adresu z duplikatami. zewnętrzne zapytanie podrzędne musi zwracać tylko jedną kolumnę, ponieważ używane jest jako operand dla operatora "= any "

 -1
Author: aad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-02 13:19:50

Odpowiedź Powerlord jest rzeczywiście najlepsza i polecam jeszcze jedną zmianę: użyj LIMIT, aby upewnić się, że db nie zostanie przeciążony:

SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address HAVING count(id) > 1) dup ON list.address = dup.address
LIMIT 10

Dobrym nawykiem jest używanie LIMIT, jeśli nie ma miejsca i podczas wykonywania połączeń. Zacznij od małej wartości, sprawdź, jak ciężkie jest zapytanie, a następnie zwiększ limit.

 -1
Author: Michał Maluga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41