web-dev-qa-db-fra.com

Trouver des valeurs en double dans MySQL

J'ai une table avec une colonne varchar et j'aimerais trouver tous les enregistrements ayant des valeurs en double dans cette colonne. Quelle est la meilleure requête que je peux utiliser pour trouver les doublons?

671
Jon Tackabury

Faites une SELECT avec une clause GROUP BY. Disons name est la colonne dans laquelle vous voulez trouver des doublons:

SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;

Cela retournera un résultat avec la valeur name dans la première colonne et le nombre de fois où cette valeur apparaîtra dans la seconde.

1346
levik
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
200
maxyfc
SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )

Cette requête renvoie des enregistrements complets, pas seulement des varchar_column distincts.

Cette requête n'utilise pas COUNT(*). S'il y a beaucoup de doublons, COUNT(*) coûte cher et vous n'avez pas besoin de la totalité de COUNT(*), vous devez simplement savoir s'il y a deux lignes de même valeur.

Avoir un index sur varchar_column accélérera bien sûr cette requête.

149
Quassnoi

En vous basant sur la réponse de levik pour obtenir les identifiants des lignes en double, vous pouvez créer un GROUP_CONCAT si votre serveur le prend en charge (cela retournera une liste d'identifiants séparés par des virgules).

SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
116
Matt Rardon
SELECT * 
FROM `dps` 
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)
12
strustam

En supposant que votre table s'appelle TableABC et que la colonne souhaitée soit Col et que la clé primaire en T1 soit Key.

SELECT a.Key, b.Key, a.Col 
FROM TableABC a, TableABC b
WHERE a.Col = b.Col 
AND a.Key <> b.Key

L'avantage de cette approche par rapport à la réponse ci-dessus est qu'elle donne la clé.

11
TechTravelThink

Pour rechercher le nombre d'enregistrements dupliqués dans la colonne Nom de Employee, la requête ci-dessous est utile.

Select name from employee group by name having count(*)>1;
9
user5599549
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

7
Lalit Patel

Ma dernière requête a incorporé quelques-unes des réponses ici qui ont aidé - combinant groupe par, compte & GROUP_CONCAT.

SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c 
FROM product_variant 
GROUP BY `magento_simple` HAVING c > 1;

Ceci fournit l'identifiant des deux exemples (séparés par des virgules), le code à barres dont j'avais besoin et le nombre de doublons.

Modifiez le tableau et les colonnes en conséquence.

6
Jonathan

Je ne vois aucune approche JOIN, qui a de nombreuses utilisations en termes de doublons 

Cette approche vous donne des résultats réels doublés.

SELECT t1.* FROM table as t1 LEFT JOIN table as t2 ON t1.name=t2.name and t1.id!=t2.id WHERE t2.id IS NOT NULL ORDER BY t1.name
6
Adam Fischer

J'ai vu le résultat ci-dessus et la requête fonctionnera correctement si vous devez vérifier la valeur d'une colonne qui est en double. Par exemple email.

Mais si vous devez vérifier avec plus de colonnes et souhaitez vérifier la combinaison du résultat, cette requête fonctionnera correctement:

SELECT COUNT(CONCAT(name,email)) AS tot,
       name,
       email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
              AND also COUNT)
5
user2235601

Prenant @ maxyfc réponse plus loin, il me fallait trouver tout des lignes renvoyées avec les valeurs en double pour pouvoir les modifier dans MySQL Workbench :

SELECT * FROM table
   WHERE field IN (
     SELECT field FROM table GROUP BY field HAVING count(*) > 1
   ) ORDER BY field
4
AbsoluteƵERØ
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
3
magesh

Ce qui suit trouvera tous les product_id qui sont utilisés plus d’une fois. Vous n'obtenez qu'un seul enregistrement pour chaque product_id.

SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1

Code provenant de: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html

3
Chandresh
CREATE TABLE tbl_master
    (`id` int, `email` varchar(15));

INSERT INTO tbl_master
    (`id`, `email`) VALUES
    (1, '[email protected]'),
    (2, '[email protected]'),
    (3, '[email protected]'),
    (4, '[email protected]'),
    (5, '[email protected]');

QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
3
Bijesh Sheth
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
2
Pawel Furmaniak

Une contribution très tardive ... au cas où cela aiderait n'importe qui à passer à travers la ligne ... j'avais la tâche de trouver des paires de transactions correspondantes (en fait, les deux côtés d'un virement de compte à compte) dans une application bancaire, pour identifier lesquelles étaient les 'de' et 'à' pour chaque transaction de transfert entre comptes, nous avons donc abouti à ceci:

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
    INNER JOIN 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
GROUP BY transactionid1
ORDER BY transactionid1;

Le résultat est que le DuplicateResultsTable fournit des lignes contenant des transactions correspondantes (c'est-à-dire dupliquées), mais il fournit également le même identifiant de transaction inversé la deuxième fois qu'il correspond à la même paire, de sorte que le SELECT extérieur est là groupez par le premier ID de transaction, en utilisant LEAST et GREATEST pour vous assurer que les deux identificateurs de transaction sont toujours dans le même ordre dans les résultats, ce qui sécurise GROUP par le premier, éliminant ainsi toutes les correspondances en double. A parcouru près d'un million de records et identifié plus de 12 000 matches en un peu moins de 2 secondes. Bien sûr, le transactionid est l’indice primaire, ce qui a vraiment aidé.

1
fortyninthnet

Pour supprimer les lignes en double avec plusieurs champs, annulez-les d'abord sur la nouvelle clé unique spécifiée pour les seules lignes distinctes puis utilisez la commande "group by" pour supprimer les lignes en double avec la même nouvelle clé unique:

Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;
1
irshst
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
1
Vipin Jain

Je préfère utiliser les fonctions fenêtrées (MySQL 8.0+) pour trouver les doublons car je pouvais voir la ligne entière:

WITH cte AS (
  SELECT *
    ,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
    ,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
  FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;

DB Fiddle Démo

1
Lukasz Szozda

pour obtenir toutes les données contenant des doublons, j’ai utilisé ceci:

SELECT * FROM TableName INNER JOIN(
  SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
  temp ON TableName.DupliactedData = temp.DupliactedData;

TableName = la table avec laquelle vous travaillez.

DupliactedData = les données dupliquées que vous recherchez.

0
udi

Essayez d'utiliser cette requête:

SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;
0
Atul Akabari
SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1
0
Scott Ferguson