6
votes

Renommer les données en double dans SQL

Je suis capable de trouver les données en double à l'aide de cette requête

  INPUT
+-----------------+               
| names           |
+-----------------+
| text1           |
| text2           |
| text3           |
| text1           |
| text3           |
| text4           |
+-----------------+

OUTPUT  
+-----------------+
| names           |
+-----------------+ 
| text1           |
| text2           |
| text3           |
| text1 new value |->RENAMED
| text3 new value |->RENAMED
| text4           |
+-----------------+


4 commentaires

Comment voudriez-vous le renommer?


quelque chose comme ajouter de nouveau avec les noms


Et que devraient-ils arriver s'il y a plus que sur duplicata? L'ajout de nouveau réduirait les doublons de 1, puis certains doublons (avec un nouveau supplémentaire) seraient dans vos données ...


ya cela réduirait les doublons et renommerait à ce nom avec de nouveaux


3 Réponses :


13
votes

En supposant que vous avez une sorte de clé primaire sur la table, comme un identifiant d'incrément automatique, vous pouvez effectuer ce qui suit. XXX PRE>

Pour expliquer, il trouvera quelque chose avec un duplicata, cueillir up l'identifiant maximum pour quoi que ce soit dans cet ensemble, puis appendez "Copier 1" à la fin de celui-ci. Vous avez peut-être encore des doublons si vous aviez des noms de 3 fois ou plus. Il suffit de l'exécuter à nouveau, cette fois avec 'copier 2' au lieu de "copier 1". Continuez à répéter ce processus jusqu'à ce que vous vous débarrassiez de tous les Duplicaates. P>

mise à jour. Pour emprunter une idée de @yahia et utilisez UUID, vous pouvez procéder comme si vous souhaitez tout faire dans une requête. P>

UPDATE group 
SET names = CONCAT(names, CONCAT ( ' Copy ', UUID_SHORT() ) )
WHERE 
ID NOT IN
(
SELECT MIN(ID) 
FROM group 
GROUP BY names 
HAVING count(*) > 1
) AND
ID IN
(
SELECT ID
FROM group AS G1
INNER JOIN group AS G2
ON G1.names = G2.names AND G1.ID <> G2.ID
);


2 commentaires

Fonctionne également pour SQL Server, il suffit de remplacer uuid_short () avec NewID (). Très belle solution! +1


Si vous obtenez une erreur 1093 - Impossible de spécifier la table cible de la mise à jour de la clause, voir Stackoverflow.com/a/45498/203915 Pour une solution de contournement



1
votes

Essayez celui-ci - xxx pré>

EDIT: strong> p>

Code complet - p>

CREATE TABLE table1(
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  names VARCHAR(255) DEFAULT NULL
);    

INSERT INTO table1 VALUES 
  ('text1'),
  ('text2'),
  ('text3'),
  ('text1'),
  ('text3'),
  ('text4');

UPDATE table1 n 
  JOIN (SELECT names, MIN(id) min_id FROM table1 GROUP BY names HAVING COUNT(*) > 1) d
    ON n.names = d.names AND n.id <> d.min_id
SET n.names = CONCAT(n.names, ' new value');

SELECT * FROM table1;

+----+-----------------+
| id | names           |
+----+-----------------+
|  1 | text1           |
|  2 | text2           |
|  3 | text3           |
|  4 | text1 new value |
|  5 | text3 new value |
|  6 | text4           |
+----+-----------------+


2 commentaires

Comme indiqué dans la sortie, comment pouvons-nous simplement remplacer une nouvelle valeur pour un nom en double


D'ACCORD. Dans ce cas, nous devrions ajouter un champ unique pour identifier les enregistrements. J'ai changé ma réponse.



2
votes

Utilisation (corrigée selon le commentaire) xxx

Ceci fait tous les doublons uniques avec une seule exécution en concaténant une uuid_short unique ... Sauf celui avec le plus petit identifiant - ça reste intact .. .


5 commentaires

Qu'en est-il des identifiants qui ne sont pas dans le maximum (id)? Cette requête ressemble beaucoup à la mine, en ce sens qu'elle sera à courir plusieurs fois, chaque fois que le max (id) est. La partie non en partie est réellement redondante, car vous ne ramassez que les identifiants max.


Qu'en est-il de la modification de la seconde en partie à: et des noms dans (sélectionnez les noms du groupe de groupe par des noms comptant (*)> 1);


@ H-man2 qui pourrait fonctionner ... Je ne sais pas que ce changement serait suffisant


En fait, cela ne fonctionnera pas, le puis que vous regroupez par nom, il ne récupérera pas tous les identifiants, mais plutôt un identifiant aléatoire (probablement d'abord) de chaque groupe de noms correspondants. MySQL est unique à cet égard en ce sens qu'il vous permet de sélectionner des colonnes, non agrégées, que vous n'avez pas inclus dans le groupement. La plupart des autres bases de données ne permettent pas de cela, car la valeur résultante n'est pas cohérente lors de l'exécution plusieurs fois sur les mêmes données.


@Kibee Vous avez raison - le changement de l'intérieur comme suggéré par H-Man2 ne fonctionnerait pas, sauf que vous incluriez une "join monstre" ...