Comment supprimer les doublons sur une table MySQL?

158

J'ai besoin de DELETElignes dupliquées pour le Sid spécifié sur une MySQLtable.

Comment puis-je faire cela avec une requête SQL?

DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"

Quelque chose comme ça, mais je ne sais pas comment faire.

Ali Demirci
la source
Avez-vous besoin de le faire une seule fois ou devez-vous le faire tout le temps?
Billy ONeal
Les enregistrements avec les enregistrements en double ont-ils tous les mêmes données, ou les autres champs sont-ils différents les uns des autres? Si vous avez la première option, vous pouvez simplement supprimer tous les enregistrements sauf un, si vous avez la deuxième option, comment déterminez-vous quel enregistrement vous souhaitez conserver?
rael_kid
@Lex Première option. @Billy j'ai besoin de le faire tout le temps.
Ali Demirci
1
duplication possible de Supprimer les lignes en double dans MySQL
Basilevs
1
Il y a beaucoup de choses qui ont changé ici dans différentes versions de MySQL. Vérifiez attentivement votre version de MySQL avant de vous lancer dans l'une des solutions proposées ici.
delatbabel

Réponses:

215

cela supprime les doublons en place, sans créer de nouvelle table

ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)

note: ne fonctionne bien que si l'index tient en mémoire

user187291
la source
26
Remarque: cela conserverait l'enregistrement en double le plus ancien et effacerait les plus récents. Si vous souhaitez conserver le plus récent, vous ne pouvez pas le faire avec ALTER IGNORE.
Haralan Dobrev
9
Ne semble pas fonctionner avec InnoDB. J'ai couru ALTER TABLE foo ENGINE MyISAMpour contourner le problème, j'ai changé le moteur après.
Martin
13
cela peut échouer sur MySQL> 5.5, si c'est le cas, utilisez "set session old_alter_table = 1;" et "set session old_alter_table = 0;" avant et après la déclaration
chillitom
2
@delatbabel La raison de sa désapprobation est donnée dans la page à laquelle vous avez lié.
Barmar
133

Supposons que vous ayez une table employee, avec les colonnes suivantes:

employee (first_name, last_name, start_date)

Pour supprimer les lignes avec une first_namecolonne en double :

delete
from employee using employee,
    employee e1
where employee.id > e1.id
    and employee.first_name = e1.first_name  
Abhijoy_D
la source
1
L'enregistrement restant aura l'identifiant maximum ou minimum dans son groupe de duplication?
Frozen Flame
L'enregistrement restant aura l'identifiant minimum car c'est le seul qui ne remplit pas la condition pour être supprimé
Pablo Guerrero
1
On dirait que la jonction employeecontre elle-même pour une correspondance d'index et une >vérification sur un index va être lente pour les grandes tables. Ne serait-il pas préférable de SELECT MAX(ID) FROM t GROUP BY uniqueet ensuite JOINune correspondance exacte de IDà MAX(ID)?
ebyrob
1
Très bonne réponse! J'ai sauvé mon temps!
Nesar le
56

Ensuite, supprimez les doublons pour tous les SID, pas seulement pour un seul.

Avec table de température

CREATE TABLE table_temp AS
SELECT * FROM table GROUP BY title, SID;

DROP TABLE table;
RENAME TABLE table_temp TO table;

Depuis sa temp_tablecréation récente, il n'a pas d'index. Vous devrez les recréer après avoir supprimé les doublons. Vous pouvez vérifier les index que vous avez dans le tableau avecSHOW INDEXES IN table

Sans table de température:

DELETE FROM `table` WHERE id IN (
  SELECT all_duplicates.id FROM (
    SELECT id FROM `table` WHERE (`title`, `SID`) IN (
      SELECT `title`, `SID` FROM `table` GROUP BY `title`, `SID` having count(*) > 1
    )
  ) AS all_duplicates 
  LEFT JOIN (
    SELECT id FROM `table` GROUP BY `title`, `SID` having count(*) > 1
  ) AS grouped_duplicates 
  ON all_duplicates.id = grouped_duplicates.id 
  WHERE grouped_duplicates.id IS NULL
)
Kamil Szot
la source
4
GROUP-ing ne produit qu'une seule ligne de résultat pour chaque combinaison de valeurs de champs que vous regroupez. Les doublons seront donc supprimés.
Kamil Szot
4
j'aime la première manière, trop élégante ici! : B
AgelessEssence
1
@fiacre Vous pouvez désactiver temporairement les vérifications de clés étrangères: stackoverflow.com/questions/15501673/ ... Vous pourriez également risquer de supprimer certaines des lignes auxquelles d'autres tables font référence, mais vous pouvez contrôler quels enregistrements sont sélectionnés dans la table dédoublée en modifiant la requête SELECT * FROM table GROUP BY title, SID;Tout dépend de la façon dont vous savez ce que vous faites.
Kamil Szot
1
@ahnbizcad Vous pouvez utiliser une table temporaire, mais vous devrez ensuite recopier les données de la table temporaire vers la table normale. Si vous utilisez une vraie table, vous pouvez simplement supprimer l'ancien avec les doublons et renommer le nouveau, sans le dupliquer en l'ancien nom.
Kamil Szot
1
La méthode "sans table temporaire" est la plus proche de la meilleure solution cependant méfiez-vous de la manipulation ONLY_FULL_GROUP_BY qui a changé dans MySQL 5.7.5: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html J'ai eu ceci travailler en remplaçant "SELECT id" par "SELECT ANY_VALUE (id) AS id"
delatbabel
53

Suppression des lignes en double dans MySQL sur place, procédure pas à pas (en supposant que vous ayez une colonne d'horodatage à trier):

Créez le tableau et insérez quelques lignes:

create table penguins(foo int, bar varchar(15), baz datetime);
insert into penguins values(1, 'skipper', now());
insert into penguins values(1, 'skipper', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(4, 'rico', now());
select * from penguins;
    +------+----------+---------------------+
    | foo  | bar      | baz                 |
    +------+----------+---------------------+
    |    1 | skipper  | 2014-08-25 14:21:54 |
    |    1 | skipper  | 2014-08-25 14:21:59 |
    |    3 | kowalski | 2014-08-25 14:22:09 |
    |    3 | kowalski | 2014-08-25 14:22:13 |
    |    3 | kowalski | 2014-08-25 14:22:15 |
    |    4 | rico     | 2014-08-25 14:22:22 |
    +------+----------+---------------------+
6 rows in set (0.00 sec)

Supprimez les doublons en place:

delete a
    from penguins a
    left join(
    select max(baz) maxtimestamp, foo, bar
    from penguins
    group by foo, bar) b
    on a.baz = maxtimestamp and
    a.foo = b.foo and
    a.bar = b.bar
    where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
select * from penguins;
+------+----------+---------------------+
| foo  | bar      | baz                 |
+------+----------+---------------------+
|    1 | skipper  | 2014-08-25 14:21:59 |
|    3 | kowalski | 2014-08-25 14:22:15 |
|    4 | rico     | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)

Vous avez terminé, les lignes en double sont supprimées, la dernière par horodatage est conservée.

Pour ceux d'entre vous sans horodatage ou colonne unique.

Vous n'avez pas de timestampcolonne d'index ou une colonne d'index unique pour trier? Vous vivez dans un état de dégénérescence. Vous devrez effectuer des étapes supplémentaires pour supprimer les lignes en double.

créer la table des pingouins et ajouter quelques lignes

create table penguins(foo int, bar varchar(15)); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(4, 'rico'); 
select * from penguins; 
    # +------+----------+ 
    # | foo  | bar      | 
    # +------+----------+ 
    # |    1 | skipper  | 
    # |    1 | skipper  | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    4 | rico     | 
    # +------+----------+ 

faites un clone de la première table et copiez-y.

drop table if exists penguins_copy; 
create table penguins_copy as ( SELECT foo, bar FROM penguins );  

#add an autoincrementing primary key: 
ALTER TABLE penguins_copy ADD moo int AUTO_INCREMENT PRIMARY KEY first; 

select * from penguins_copy; 
    # +-----+------+----------+ 
    # | moo | foo  | bar      | 
    # +-----+------+----------+ 
    # |   1 |    1 | skipper  | 
    # |   2 |    1 | skipper  | 
    # |   3 |    3 | kowalski | 
    # |   4 |    3 | kowalski | 
    # |   5 |    3 | kowalski | 
    # |   6 |    4 | rico     | 
    # +-----+------+----------+ 

L'agrégat max fonctionne sur le nouvel index moo:

delete a from penguins_copy a left join( 
    select max(moo) myindex, foo, bar 
    from penguins_copy 
    group by foo, bar) b 
    on a.moo = b.myindex and 
    a.foo = b.foo and 
    a.bar = b.bar 
    where b.myindex IS NULL; 

#drop the extra column on the copied table 
alter table penguins_copy drop moo; 
select * from penguins_copy; 

#drop the first table and put the copy table back: 
drop table penguins; 
create table penguins select * from penguins_copy; 

observer et nettoyer

drop table penguins_copy; 
select * from penguins;
+------+----------+ 
| foo  | bar      | 
+------+----------+ 
|    1 | skipper  | 
|    3 | kowalski | 
|    4 | rico     | 
+------+----------+ 
    Elapsed: 1458.359 milliseconds 

Que fait cette grosse instruction de suppression SQL?

Les pingouins de table avec l'alias «a» sont laissés joints sur un sous-ensemble de pingouins de table appelé alias «b». La table de droite 'b' qui est un sous-ensemble trouve l'horodatage max [ou max moo] groupé par les colonnes foo et bar. Cela correspond au tableau de gauche «a». (foo, bar, baz) sur la gauche a toutes les lignes du tableau. Le sous-ensemble de droite 'b' a un (maxtimestamp, foo, bar) qui correspond à gauche uniquement sur celui qui EST le max.

Chaque ligne qui n'est pas ce max a pour valeur maxtimestamp NULL. Filtrez vers le bas sur ces lignes NULL et vous avez un ensemble de toutes les lignes regroupées par foo et bar qui ne sont pas le dernier horodatage baz. Supprimez-les.

Faites une sauvegarde de la table avant de l'exécuter.

Empêchez ce problème de se reproduire sur cette table:

Si cela fonctionne, et que cela éteint votre feu de "ligne en double". Génial. Définissez maintenant une nouvelle clé unique composite sur votre table (sur ces deux colonnes) pour éviter que d'autres doublons ne soient ajoutés en premier lieu.

Comme un bon système immunitaire, les mauvaises lignes ne devraient même pas être autorisées à entrer sur la table au moment de l'insertion. Plus tard, tous ces programmes ajoutant des doublons diffuseront leur protestation, et lorsque vous les corrigerez, ce problème ne se reproduira plus.

Eric Leschinski
la source
6
notez uniquement pour la référence de Madagascar!
Michael Wiggins
1
Évalué car c'est une excellente réponse et d'excellentes suggestions, merci Eric a mieux travaillé que toute autre réponse là-bas.
johan
4
Remarque: Si votre table a une IDcolonne à incrémentation automatique , la ONclause doit uniquement correspondre à la IDcolonne, rien d'autre.
ebyrob
1
J'aime l'explication détaillée mais ... Si je comprends bien, cette réponse utilise l'horodatage pour distinguer les enregistrements. En ce sens, les enregistrements ne sont pas dupliqués. Que faire si vous n'avez pas d'horodatage pour distinguer les enregistrements, c'est-à-dire que toutes les colonnes sont identiques pour 2 enregistrements ou plus?
Rsc Rsc
1
@RscRsc Si vous n'avez pas de colonne d'horodatage ou d'index unique auquel appliquer l'agrégat maximum, il semble que vous deviez dupliquer la table, ajouter un index unique, appliquer l'instruction de suppression, puis remplacer la table copiée par l'original . J'ai changé la réponse pour refléter ces instructions.
Eric Leschinski
16

Après avoir rencontré ce problème moi-même, sur une énorme base de données, je n'ai pas été complètement impressionné par la performance de l'une des autres réponses. Je souhaite ne conserver que la dernière ligne en double et supprimer le reste.

Dans une instruction à une seule requête, sans table temporaire, cela a fonctionné mieux pour moi,

DELETE e.*
FROM employee e
WHERE id IN
 (SELECT id
   FROM (SELECT MIN(id) as id
          FROM employee e2
          GROUP BY first_name, last_name
          HAVING COUNT(*) > 1) x);

La seule mise en garde est que je dois exécuter la requête plusieurs fois, mais même avec cela, j'ai trouvé que cela fonctionnait mieux pour moi que les autres options.

seaders
la source
1
Solution pragmatique! A travaillé pour moi - environ 20 s pour une table innodb de 2 m + rangée. Une fois, je l'ai utilisé à quelques reprises et je me suis retrouvé à quelques délinquants avec un nombre élevé de doublons, j'ai terminé le travail manuellement.
Troy Wray
1
A travaillé pour moi en un seul passage, génial!
Murwa
Il doit être exécuté plusieurs fois si les doublons pour l'une des colonnes sont plus de 2x
PayteR
@PayteR qui est indiqué dans la réponse, "La seule mise en garde est que je dois exécuter la requête plusieurs fois"
seaders
13

Cela semble toujours fonctionner pour moi:

CREATE TABLE NoDupeTable LIKE DupeTable; 
INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;

Ce qui conserve l'ID le plus bas sur chacune des dupes et le reste des enregistrements non-dupes.

J'ai également pris les mesures suivantes pour que le problème de dupe ne se produise plus après la suppression:

CREATE TABLE NoDupeTable LIKE DupeTable; 
Alter table NoDupeTable Add Unique `Unique` (CommonField1,CommonField2);
INSERT IGNORE NoDupeTable SELECT * FROM DupeTable;

En d'autres termes, je crée un duplicata de la première table, j'ajoute un index unique sur les champs dont je ne veux pas de duplicata, puis j'en fais un Insert IGNOREqui a l'avantage de ne pas échouer comme d'habitude le Insertferait la première fois qu'il essaie d'ajouter un enregistrement en double basé sur les deux champs et ignore plutôt ces enregistrements.

En se déplaçant vers l'avant, il devient impossible de créer des enregistrements en double basés sur ces deux champs.

user3649739
la source
1
N'auriez-vous pas besoin d'un ORDER BYdans le SELECTpour être sûr de quel disque est réellement passé au NoDupeTable?
ebyrob
@ebyrob Je crois que sauf indication contraire, il sélectionnera l'ID le plus bas en l'absence d'autres critères. Bien sûr , ORDER by ID Ascne peut pas nuire , donc je vais modifier ma nontheless de réponse.
user3649739
@ebyrob Désolé mon mal. Commander par ne fonctionnera pas dans cette sélection à ma connaissance. Un ordre par à la fin de la sélection ne classera que les doublons trouvés par l'ID le plus bas trouvé dans chaque paire. Alternativement, vous pouvez faire un Select Max(ID)et ensuite, Order by Max(ID)mais tout ce que cela ferait est d'inverser l'ordre de l'insertion. Pour saisir l'ID le plus élevé, il faudrait, je crois, une jointure de sélection plus complexe car, quelle que soit la façon dont vous commandez ci-dessus, vous récupérerez les valeurs de champ de l'ID inférieur.
user3649739
En fait, je ne sais pas à quoi je pensais avec ordre. Vous voudriez certainement des noms de colonne MAX(ID)ou MIN(ID)et au lieu de *dans le SELECT FROM DupeTablecependant, sinon vous obtiendrez simplement l'un des noms au IDhasard. En fait, de nombreux SQL et même MySQL strict nécessitent l'appel d'une fonction d'agrégation sur chaque colonne non spécifiée dans la GROUP BYclause.
ebyrob
@ebyrob Lors du test de Max (ID) Min (ID), ne rien faire d'autre que renvoyer l'ID de l'enregistrement Max ou Mind. Dans chaque cas attrape les mêmes enregistrements. Donc, si j'avais deux enregistrements avec des champs ID,First,Last,Noteset des enregistrements 1,Bob,Smith,NULL, 2,Bob,Smith,Arrearspuis que SELECT *Max(ID), First,Last,Notes FROM DupeTable group by First,Lastje faisais un , les deux renverraient le même enregistrement, 1, sauf avec un ID différent. Max (ID) reviendrait 2,Bob,Smith,NULLet Min (ID) reviendrait 1,Bob,Smith,NULL. Pour obtenir le deuxième enregistrement avec «Arriérés» dans les notes, il faut une jointure, je crois.
user3649739
7

Ce qui suit fonctionne pour toutes les tables

CREATE TABLE `noDup` LIKE `Dup` ;
INSERT `noDup` SELECT DISTINCT * FROM `Dup` ;
DROP TABLE `Dup` ;
ALTER TABLE `noDup` RENAME `Dup` ;
MBMiri
la source
6

Voici une réponse simple:

delete a from target_table a left JOIN (select max(id_field) as id, field_being_repeated  
    from target_table GROUP BY field_being_repeated) b 
    on a.field_being_repeated = b.field_being_repeated
      and a.id_field = b.id_field
    where b.id_field is null;
Ted Célestin
la source
C'est une bonne réponse, sauf une petite erreurand a.id_field = b.id
Vikrant Goel
Le LEFT JOINà bn'a besoin que de comparer b.id= en a.id_fieldsupposant qu'il field_ids'agit d'un ID d'incrémentation automatique unique. a.field_being_repeated = b.field_being_repeatedest donc étranger. ( b.id_fieldn'existe pas non plus dans cette requête, c'est b.id.
ebyrob
6

Ce travail pour moi de supprimer les anciens enregistrements:

delete from table where id in 
(select min(e.id)
    from (select * from table) e 
    group by column1, column2
    having count(*) > 1
); 

Vous pouvez remplacer min (e.id) par max (e.id) pour supprimer les enregistrements les plus récents.

Richardhell
la source
5
delete p from 
product p
inner join (
    select max(id) as id, url from product 
    group by url 
    having count(*) > 1
) unik on unik.url = p.url and unik.id != p.id;
temonehm
la source
1
J'ai trouvé qu'une solution beaucoup plus performante que celles ci
Christian Butzke
5

Je trouve que la solution de Werner ci-dessus est la plus pratique car elle fonctionne quelle que soit la présence d'une clé primaire, ne joue pas avec les tables, utilise un SQL simple à l'épreuve du temps, est très compréhensible.

Comme je l'ai dit dans mon commentaire, cette solution n'a cependant pas été correctement expliquée. C'est donc à moi, basé sur cela.

1) ajouter une nouvelle colonne booléenne

alter table mytable add tokeep boolean;

2) ajouter une contrainte sur les colonnes dupliquées ET la nouvelle colonne

alter table mytable add constraint preventdupe unique (mycol1, mycol2, tokeep);

3) définissez la colonne booléenne sur true. Cela ne réussira que sur l'une des lignes dupliquées en raison de la nouvelle contrainte

update ignore mytable set tokeep = true;

4) supprimer les lignes qui n'ont pas été marquées comme à conserver

delete from mytable where tokeep is null;

5) Déposez la colonne ajoutée

alter table mytable drop tokeep;

Je vous suggère de conserver la contrainte que vous avez ajoutée, afin d'éviter de nouveaux doublons à l'avenir.

xtian
la source
4

Cette procédure supprimera tous les doublons (y compris les multiples) dans une table, en conservant le dernier duplicata. Ceci est une extension de Récupération du dernier enregistrement dans chaque groupe

J'espère que cela est utile à quelqu'un.

DROP TABLE IF EXISTS UniqueIDs;
CREATE Temporary table UniqueIDs (id Int(11));

INSERT INTO UniqueIDs
    (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON
    (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields 
    AND T1.ID < T2.ID)
    WHERE T2.ID IS NULL);

DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);
Simon
la source
4

Un autre moyen simple ... en utilisant UPDATE IGNORE:

Vous devez utiliser un index sur une ou plusieurs colonnes (type index). Créez une nouvelle colonne de référence temporaire (ne faisant pas partie de l'index). Dans cette colonne, vous marquez les uniques en la mettant à jour avec la clause ignore. Pas à pas:

Ajoutez une colonne de référence temporaire pour marquer les uniques:

ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;

=> cela ajoutera une colonne à votre table.

Mettez à jour la table, essayez de tout marquer comme unique, mais ignorez les erreurs possibles dues à un problème de clé en double (les enregistrements seront ignorés):

UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;

=> vous verrez que vos enregistrements en double ne seront pas marqués comme uniques = 'Oui', en d'autres termes, un seul de chaque ensemble d'enregistrements en double sera marqué comme unique.

Supprimez tout ce qui n'est pas unique:

DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';

=> Cela supprimera tous les enregistrements en double.

Déposez la colonne ...

ALTER TABLE `yourtable` DROP `unique`;
Werner
la source
Je pense que c'est la meilleure solution car elle ne gâche pas les tables et utilise un simple SQL. Une seule chose doit être clarifiée: la uniquecolonne DOIT être ajoutée à une contrainte unique avec les colonnes qui sont actuellement dupliquées, sinon tout ne fonctionne pas car SET unique= 'Yes' n'échouerait jamais.
xtian
Sachez également qu'il uniques'agit d'un mot clé mysql. Il doit donc avoir les backticks (comme déjà correctement affichés). Utiliser un autre mot pour la colonne peut être plus pratique.
Torsten
2

La suppression des doublons sur les tables MySQL est un problème courant, qui vient généralement avec des besoins spécifiques. Au cas où quelqu'un serait intéressé, ici ( Supprimer les lignes en double dans MySQL ) J'explique comment utiliser une table temporaire pour supprimer les doublons de MySQL de manière fiable et rapide, également valable pour gérer les sources de données volumineuses (avec des exemples pour différents cas d'utilisation).

Ali , dans votre cas, vous pouvez exécuter quelque chose comme ceci:

-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;

-- add a unique constraint    
ALTER TABLE tmp_table1 ADD UNIQUE(sid, title);

-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;

-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;
César Revert-Gomar
la source
0
delete from `table` where `table`.`SID` in 
    (
    select t.SID from table t join table t1 on t.title = t1.title  where t.SID > t1.SID
)
Patrick
la source
Cela génère une erreur SQL (1093) sur certaines configurations et versions de MySQL.
ebyrob
0

J'adore la réponse de @ eric, mais cela ne semble pas fonctionner si vous avez une très grande table (je reçois The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okayquand j'essaye de l'exécuter). J'ai donc limité la requête de jointure pour ne considérer que les lignes en double et je me suis retrouvé avec:

DELETE a FROM penguins a
    LEFT JOIN (SELECT COUNT(baz) AS num, MIN(baz) AS keepBaz, foo
        FROM penguins
        GROUP BY deviceId HAVING num > 1) b
        ON a.baz != b.keepBaz
        AND a.foo = b.foo
    WHERE b.foo IS NOT NULL

La clause WHERE dans ce cas permet à MySQL d'ignorer toute ligne qui n'a pas de doublon et ignorera également s'il s'agit de la première instance du doublon, donc seuls les doublons suivants seront ignorés. Remplacez MIN(baz)par MAX(baz)pour conserver la dernière instance au lieu de la première.

Gujamin
la source
0

Cela fonctionne pour les grandes tables:

 CREATE Temporary table duplicates AS select max(id) as id, url from links group by url having count(*) > 1;

 DELETE l from links l inner join duplicates ld on ld.id = l.id WHERE ld.id IS NOT NULL;

Pour supprimer la modification la plus ancienne max(id)demin(id)

Mugoma J. Okomba
la source
0

Ceci transformera la colonne column_nameen clé primaire et ignorera en attendant toutes les erreurs. Ainsi, il supprimera les lignes avec une valeur en double pour column_name.

ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);
Abraham Murciano Benzadon
la source
Comme indiqué dans les commentaires sur la réponse précédente, cela ne fonctionne plus dans 5.7.
Barmar
0

Je pense que cela fonctionnera essentiellement en copiant la table et en la vidant, puis en n'y remettant que les valeurs distinctes, mais veuillez le vérifier avant de le faire sur de grandes quantités de données.

Crée une copie carbone de votre table

créer une table temp_table comme oldtablename; insert temp_table select * from oldtablename;

Vide votre table d'origine

DELETE * de l'ancien nom de la table;

Copie toutes les valeurs distinctes de la table copiée dans votre table d'origine

INSÉRER oldtablename SELECT * du groupe temp_table par prénom, nom, dob

Supprime votre table temporaire.

Drop Table temp_table

Vous devez regrouper tous les champs que vous souhaitez conserver distincts.

ChrisAardvark
la source
0
DELETE T2
FROM   table_name T1
JOIN   same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)
Nav
la source
cela ne fonctionne pas votre demande, pourriez-vous l'améliorer?
Samir Guiderk le
0

voici comment j'élimine habituellement les doublons

  1. ajoutez une colonne temporaire, nommez-la comme vous le souhaitez (je ferai référence à active)
  2. groupez par les champs qui, selon vous, ne devraient pas être dupliqués et définissez leur actif sur 1, le groupement par sélectionnera une seule des valeurs en double (ne sélectionnera pas les doublons) pour ces colonnes
  3. supprimer ceux avec zéro actif
  4. déposer la colonne active
  5. facultativement (si cela correspond à vos objectifs), ajoutez un index unique pour que ces colonnes n'aient plus de doublons
Yazgan
la source
-2

Vous pouvez simplement utiliser une clause DISTINCT pour sélectionner la liste "nettoyée" (et voici un exemple très simple sur la façon de procéder).

Rosamunda
la source
Comment cela répond-il à la question? En utilisant DISTINCTvous, vous perdez toutes les informations sur les doublons que vous auriez pu avoir en premier lieu. Pouvez-vous montrer un moyen de supprimer les doublons en l'utilisant?
luk2302
-3

Cela pourrait-il fonctionner si vous les comptez, puis ajoutez une limite à votre requête de suppression en n'en laissant qu'une?

Par exemple, si vous en avez deux ou plus, écrivez votre requête comme ceci:

DELETE FROM table WHERE SID = 1 LIMIT 1;
user3325657
la source
-5

Il n'y a que quelques étapes de base pour supprimer les données en double de votre table:

  • Sauvegardez votre table!
  • Trouvez les lignes en double
  • Supprimer les lignes en double

Voici le tutoriel complet: https://blog.teamsql.io/deleting-duplicate-data-3541485b3473

Pouvez
la source
Cela fonctionne-t-il si seulement un identifiant unique est différent. Eğer sadece benzersiz id farklı ise de bu işe yarar mı?
Andrew
Par défaut, la méthode décrite ici ne fonctionne pas pour les versions MySQL> 5.7.5. Cela est dû à la gestion de ONLY_FULL_GROUP_BY. Voir ici: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
delatbabel