J'ai une table avec une colonne varchar, et je voudrais trouver tous les enregistrements qui ont des valeurs en double dans cette colonne. Quelle est la meilleure requête que je puisse utiliser pour trouver les doublons?
J'ai une table avec une colonne varchar, et je voudrais trouver tous les enregistrements qui ont des valeurs en double dans cette colonne. Quelle est la meilleure requête que je puisse utiliser pour trouver les doublons?
Réponses:
Faites un SELECT
avec une GROUP BY
clause. Disons que le nom est la colonne dans laquelle vous souhaitez trouver des doublons:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
Cela renverra un résultat avec la valeur du nom dans la première colonne et un nombre de fois que cette valeur apparaîtra dans la seconde.
GROUP_CONCAT(id)
et il listera les identifiants. Voir ma réponse pour un exemple.
ERROR: column "c" does not exist LINE 1
?
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
IN()
/ NOT IN()
.
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 enregistrements distincts varchar_column
.
Cette requête n'utilise pas COUNT(*)
. S'il y a beaucoup de doublons, COUNT(*)
coûte cher et que vous n'avez pas besoin du tout COUNT(*)
, il vous suffit de savoir s'il y a deux lignes de même valeur.
varchar_column
Bien entendu, avoir un index accélérera considérablement cette requête.
ORDER BY varchar_column DESC
à la fin de la requête.
GROUP BY
et HAVING
ne renvoie qu'un seul des doublons possibles. En outre, les performances avec un champ indexé au lieu de COUNT(*)
, et la possibilité ORDER BY
de regrouper les enregistrements en double.
À partir de la réponse de levik pour obtenir les ID des lignes en double, vous pouvez le faire GROUP_CONCAT
si votre serveur le prend en charge (cela renverra une liste d'ID séparés par des virgules).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
il permet la modification en ligne et il devrait mettre à jour toutes les lignes impliquées (ou au moins la première correspondante), mais malheureusement, la modification génère une erreur Javascript. ..
En supposant que votre table est nommée TableABC et la colonne que vous souhaitez est Col et la clé primaire de T1 est 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 sur la réponse ci-dessus est qu'elle donne la clé.
Pour trouver combien d'enregistrements sont des doublons dans la colonne de nom dans Employé, la requête ci-dessous est utile;
Select name from employee group by name having count(*)>1;
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.
Ma dernière requête a incorporé ici quelques-unes des réponses qui ont aidé - en combinant group by, count & GROUP_CONCAT.
SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c
FROM product_variant
GROUP BY `magento_simple` HAVING c > 1;
Cela fournit l'id 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.
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 my_table as t1
LEFT JOIN my_table as t2
ON t1.name=t2.name and t1.id!=t2.id
WHERE t2.id IS NOT NULL
ORDER BY t1.name
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 la ville par votre table. Remplacez le nom par le nom de votre champ
Pour aller plus loin dans la réponse de @ maxyfc , j'avais besoin de trouver toutes les lignes renvoyées avec les valeurs en double, afin de 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
J'ai vu le résultat ci-dessus et la requête fonctionnera bien si vous devez vérifier la valeur d'une seule colonne qui est en double. Par exemple, e-mail.
Mais si vous avez besoin de vérifier avec plus de colonnes et que vous 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)
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Je préfère utiliser des fonctions fenêtrées (MySQL 8.0+) pour trouver des 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;
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
Ce qui suit trouvera tous les product_id qui sont utilisés plus d'une fois. Vous obtenez un seul enregistrement pour chaque product_id.
SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1
Code tiré de: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
CREATE TABLE tbl_master
(`id` int, `email` varchar(15));
INSERT INTO tbl_master
(`id`, `email`) VALUES
(1, 'test1@gmail.com'),
(2, 'test2@gmail.com'),
(3, 'test1@gmail.com'),
(4, 'test2@gmail.com'),
(5, 'test5@gmail.com');
QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
a.email
à a.*
et obtenir tous les ID des lignes avec des doublons.
SELECT DISTINCT a.*
résolu presque instantanément.
Pour supprimer les lignes en double avec plusieurs champs, annulez-les d'abord à la nouvelle clé unique qui est 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;
CREATE TEMPORARY TABLE ...
? Une petite explication de votre solution serait formidable.
Une contribution très tardive ... au cas où cela aiderait quiconque à waaaaaay sur la ligne ... J'ai eu la tâche de trouver des paires de transactions correspondantes (en fait des deux côtés des transferts de compte à compte) dans une application bancaire, pour identifier celles étaient le «de» et le «à» pour chaque transaction de transfert entre comptes, nous nous sommes donc retrouvés avec 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 en double), mais il fournit également les mêmes identifiants de transaction en sens inverse la deuxième fois qu'il correspond à la même paire, de sorte que l'extérieur SELECT
est là pour regrouper par le premier ID de transaction, ce qui est fait en utilisant LEAST
et GREATEST
pour vous assurer que les deux transactionid sont toujours dans le même ordre dans les résultats, ce qui le rend sûr GROUP
par le premier, éliminant ainsi toutes les correspondances en double. Parcourez près d'un million de records et identifié plus de 12 000 matchs en un peu moins de 2 secondes. Bien sûr, le transactionid est l'indice principal, ce qui a vraiment aidé.
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1
Si vous souhaitez supprimer l'utilisation en double DISTINCT
Sinon, utilisez cette requête:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
Essayez d'utiliser cette requête:
SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;