web-dev-qa-db-fra.com

Trouver des enregistrements en double dans MySQL

Je veux extraire des enregistrements en double dans une base de données MySQL. Cela peut être fait avec:

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

Ce qui résulte en:

100 MAIN ST    2

Je voudrais le tirer de sorte qu'il montre chaque ligne qui est un doublon. Quelque chose comme:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

Des idées sur la façon dont cela peut être fait? J'essaie d'éviter de faire la première, puis de rechercher les doublons avec une deuxième requête dans le code.

617
Chris Bartow

La clé est de réécrire cette requête afin qu'elle puisse être utilisée comme une sous-requête.

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;
655
Powerlord
SELECT date FROM logs group by date having count(*) >= 2
338
trt

Pourquoi ne pas simplement INNER JOIN la table avec lui-même?

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

Un DISTINCT est nécessaire si l'adresse peut exister plus de deux fois.

193
rudolfson

J'ai essayé la meilleure réponse choisie pour cette question, mais cela m'a un peu dérouté. En fait, je n'avais besoin de cela que sur un seul champ de ma table. L'exemple suivant de ce lien a très bien fonctionné pour moi:

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;
53
Arman Malik
select `cityname` from `codcities` group by `cityname` having count(*)>=2

C’est la requête similaire que vous avez demandée et elle est simple et efficace à 200%. Prendre plaisir!!!

42
pratswinz

Rechercher les utilisateurs en double par adresse e-mail avec cette requête ...

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;
35
doublejosh

N'est-ce pas plus facile:

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

?

26
Tudor

nous pouvons trouver les doublons dépend de plus d'un champs également.Pour les cas, vous pouvez utiliser le format ci-dessous.

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;
19

Une autre solution consisterait à utiliser des alias de table, comme suit:

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

Tout ce que vous faites réellement dans ce cas prend la table liste originale, en créant deux tables p retend - p 1 et p 2 - et exécutez ensuite une jointure sur la colonne d'adresse (ligne 3). La 4ème ligne vérifie que le même enregistrement ne s'affiche pas plusieurs fois dans votre jeu de résultats ("doublons en double").

13
jerdiggity

Trouver des adresses en double est beaucoup plus complexe qu'il n'y parait, surtout si vous avez besoin de précision. Une requête MySQL ne suffit pas dans ce cas ...

Je travaille chez SmartyStreets , où nous abordons la validation et la déduplication, entre autres choses, et j'ai été témoin de nombreux problèmes variés présentant des problèmes similaires.

Il existe plusieurs services tiers qui marqueront les doublons dans une liste pour vous. Faire cela uniquement avec une sous-requête MySQL ne tiendra pas compte des différences dans les formats d'adresses et les normes. USPS (pour les États-Unis) a certaines directives pour rendre ces normes standards, mais seuls quelques fournisseurs sont certifiés pour effectuer de telles opérations.

Je vous recommande donc la meilleure solution, à savoir exporter la table dans un fichier CSV, par exemple, et la soumettre à un système de traitement de liste capable. Un tel est LiveAddress qui le fera pour vous dans quelques secondes à quelques minutes automatiquement. Il va marquer les lignes en double avec un nouveau champ appelé "Dupliquer" et une valeur de Y.

11
Matt

Ça ne va pas être très efficace, mais ça devrait marcher:

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;
10
Chad Birch

Cela sélectionnera les doublons dans une passe de table, pas de sous-requêtes.

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

Cette requête émule effectivement ROW_NUMBER() présente dans Oracle et SQL Server

Voir l'article sur mon blog pour plus de détails:

10
Quassnoi

Cela vous indiquera également le nombre de doublons et ordonnera les résultats sans jointures.

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC
7
Martin Tonev

Personnellement, cette requête a résolu mon problème:

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

Ce script affiche tous les ID d'abonné qui existent plusieurs fois dans la table et le nombre de doublons trouvés.

Ce sont les colonnes de la table:

| 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    |                |

J'espère que ça vous sera utile non plus!

4
Ionut Petre

Procédure de requête de suppression des doublons la plus rapide:

/* 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
venkatesh
 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)
4
Ryan Roper
select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

Pour votre table, ce serait quelque chose comme

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

Cette requête vous donnera toutes les entrées d'adresses distinctes dans votre table de liste ... Je ne sais pas comment cela fonctionnera si vous avez des valeurs de clé primaire comme nom, etc.

4
Neha Patil
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

Remplacez ville par votre table. Remplacez name par votre nom de champ

3
Lalit Patel
    SELECT *
    FROM (SELECT  address, COUNT(id) AS cnt
    FROM list
    GROUP BY address
    HAVING ( COUNT(id) > 1 ))
2
DJ.
    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 |
+---------------------+------------+---+
0
Usman Yaqoob

Pour voir rapidement les lignes en double, vous pouvez exécuter une seule requête simple

Ici, j'interroge la table et répertorie toutes les lignes en double avec les mêmes id_utilisateur, market_place et 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;

Pour supprimer la ligne en double, vous devez choisir la ligne à supprimer. Par exemple, celui avec un identifiant inférieur (généralement plus ancien) ou peut-être une autre information de date. Dans mon cas, je veux juste supprimer l’identifiant inférieur car l’identificateur le plus récent contient les dernières informations.

Commencez par vérifier si les bons enregistrements seront supprimés. Ici, je sélectionne l’enregistrement parmi les doublons qui seront supprimés (par identifiant unique).

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;

Ensuite, je lance la requête de suppression pour supprimer les dupes:

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;

Sauvegarde, double vérification, vérification, vérification de sauvegarde, puis exécution.

0
Ganesh Krishnan

Powerlord answer est en effet le meilleur et je recommanderais un autre changement: utilisez LIMIT pour vous assurer que la base de données ne sera pas surchargée:

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

C'est une bonne habitude d'utiliser LIMIT s'il n'y a pas de WHERE et lors de la création de jointures. Commencez avec une valeur faible, vérifiez le poids de la requête, puis augmentez la limite.

0
Michał Maluga