web-dev-qa-db-fra.com

Supprimer tous les enregistrements en double sauf un

J'ai une table qui est censée garder une trace des visiteurs d'un profil donné (identifiant utilisateur à paire identifiant utilisateur). Il s'avère que ma requête SQL était un peu éteinte et produit plusieurs paires au lieu de simples comme prévu. Avec du recul, j'aurais dû appliquer une contrainte unique sur chaque paire id + id.

Maintenant, comment pourrais-je nettoyer la table? Ce que je veux faire, c'est supprimer toutes les paires en double et n'en laisser qu'une seule.

Donc, par exemple, changez ceci:

23515 -> 52525 date_visited
23515 -> 52525 date_visited
23515 -> 52525 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
23515 -> 52525 date_visited
...

En cela:

23515 -> 52525 date_visited
12345 -> 54321 date_visited

Mise à jour: voici la structure du tableau comme demandé:

id  int(10)         UNSIGNED    Non     Aucun   AUTO_INCREMENT
profile_id  int(10)         UNSIGNED    Non     0 
visitor_id  int(10)         UNSIGNED    Non     0
date_visited    timestamp           Non     CURRENT_TIMESTAMP   
33
James P.

Utilisez group by dans une sous-requête:

delete from my_tab where id not in 
(select min(id) from my_tab group by profile_id, visitor_id);

Vous avez besoin d'une sorte d'identifiant unique (ici, j'utilise id).

[~ # ~] mise à jour [~ # ~]

Comme l'a souligné @JamesPoulson, cela provoque une erreur de syntaxe dans MySQL; la bonne solution est (comme indiqué dans réponse de James ):

delete from `my_tab` where id not in
( SELECT * FROM 
    (select min(id) from `my_tab` group by profile_id, visitor_id) AS temp_tab
);
48
Frank Schmitt

Voici la solution de Frank Schmitt avec une petite solution de contournement pour la table temporaire:

delete from `my_tab` where id not in
( SELECT * FROM 
    (select min(id) from `my_tab` group by profile_id, visitor_id) AS temp_tab
)
14
James P.

Cela fonctionnera:

With NewCTE
AS
(
Select *, Row_number() over(partition by ID order by ID)as RowNumber from 
table_name
)
Delete from NewCTE where RowNumber > 1
3
Vik Wilder

Sélectionnez toutes les lignes uniques
Copiez-les dans une nouvelle table temporaire
Tronquer le tableau d'origine
Copier les données de la table temporaire dans la table d'origine

C'est ce que je ferais. Je ne sais pas s'il y a 1 requête qui ferait tout cela pour vous.

2
gmadd