Quelle est la meilleure façon de supprimer les lignes en double d'une SQL Server
table assez grande (c'est-à-dire plus de 300 000 lignes)?
Les lignes, bien sûr, ne seront pas des doublons parfaits en raison de l'existence du RowID
champ d'identité.
Ma table
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
sql-server
tsql
duplicates
Seibar
la source
la source
DELETE FROM
directement utiliser un terme CTE. Voir stackoverflow.com/q/18439054/398670ROWID()
fonction par la colonne RowID, le cas échéant)Réponses:
En supposant qu'aucune valeur nulle, vous
GROUP BY
les colonnes uniques etSELECT
leMIN (or MAX)
RowId comme ligne à conserver. Ensuite, supprimez tout ce qui n'a pas d'ID de ligne:Si vous avez un GUID au lieu d'un entier, vous pouvez remplacer
avec
la source
DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
LEFT JOIN
est moins efficace queNOT EXISTS
sqlinthewild.co.za/index.php/2010/03/23/... Le même site compare égalementNOT IN
vsNOT EXISTS
. sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in Sur les 3, je pense que lesNOT EXISTS
meilleurs résultats. Tous les trois généreront un plan avec une auto-jointure, mais cela peut être évité.DELETE MyTable FROM MyTable
la syntaxe est-elle correcte? Je ne vois pas de mettre le nom de la table juste après l'DELETE
option comme option dans la documentation ici . Désolé si cela est évident pour les autres; Je suis un débutant en SQL essayant juste d'apprendre. Plus important que pourquoi cela fonctionne-t-il: quelle est la différence entre y inclure ou non le nom de la table?Une autre façon possible de le faire est
J'utilise ci-
ORDER BY (SELECT 0)
dessus car il est arbitraire quelle ligne conserver en cas d'égalité.Pour conserver la dernière version
RowID
afin, par exemple, vous pouvez utiliserORDER BY RowID DESC
Plans d'exécution
Le plan d'exécution pour cela est souvent plus simple et plus efficace que celui de la réponse acceptée car il ne nécessite pas l'auto-jointure.
Ce n'est cependant pas toujours le cas. Un endroit où la
GROUP BY
solution pourrait être préférée est les situations où un agrégat de hachage serait choisi de préférence à un agrégat de flux.La
ROW_NUMBER
solution donnera toujours à peu près le même plan alors que laGROUP BY
stratégie est plus flexible.Les facteurs qui pourraient favoriser l'approche globale du hachage seraient:
Dans les versions extrêmes de ce deuxième cas (s'il y a très peu de groupes avec de nombreux doublons dans chacun), on pourrait également envisager d'insérer simplement les lignes à conserver dans une nouvelle table, puis de
TRUNCATE
copier l'original et de les recopier pour minimiser la journalisation par rapport à la suppression d'un très grande proportion de rangées.la source
uniqueidentifier
. Celui-ci est beaucoup plus simple et fonctionne parfaitement sur n'importe quelle table. Merci Martin.RowId
) pour comparer.Il y a un bon article sur la suppression des doublons sur le site de support Microsoft. C'est assez conservateur - ils vous font tout faire dans des étapes distinctes - mais cela devrait bien fonctionner contre de grandes tables.
J'ai utilisé des auto-jointures pour le faire dans le passé, même si cela pourrait probablement être agrémenté d'une clause HAVING:
la source
La requête suivante est utile pour supprimer des lignes en double. La table de cet exemple a
ID
une colonne d'identité et les colonnes contenant des données en double sontColumn1
,Column2
etColumn3
.Le script suivant montre l' utilisation de
GROUP BY
,HAVING
,ORDER BY
dans une requête, et renvoie les résultats avec colonne en double et son compte.la source
NOT IN
il fonctionne souvent mieux queOUTER JOIN ... NULL
. J'ajouterais unHAVING MAX(ID) IS NOT NULL
à la requête bien que même sémantiquement cela ne devrait pas être nécessaire car cela peut améliorer l' exemple dePostgres:
la source
la source
Cela supprimera les lignes en double, sauf la première ligne
Reportez-vous ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )
la source
Je préférerais CTE pour supprimer les lignes en double de la table du serveur SQL
recommande fortement de suivre cet article :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/
la source
Pour récupérer des lignes en double:
Pour supprimer les lignes en double:
la source
DELETE FROM
, deuxièmement, cela ne fonctionnera pas, car vous ne pouvez pas àSELECT
partir de la même table que vous utilisezDELETE
. Dans MySQL, cela décolleMySQL error 1093
.Rapide et sale pour supprimer les lignes dupliquées exactes (pour les petites tables):
la source
Je préfère la sous-requête \ ayant la solution count (*)> 1 à la jointure interne car je l'ai trouvée plus facile à lire et il était très facile de se transformer en une instruction SELECT pour vérifier ce qui serait supprimé avant de l'exécuter.
la source
MAX(id)
pour éliminer les derniers doublons et ajoutéLIMIT 1000000
à la requête interne afin qu'il n'ait pas à analyser toute la table. Cela a montré des progrès beaucoup plus rapides que les autres réponses, qui semblaient se bloquer pendant des heures. Une fois que la table a été élaguée à une taille gérable, vous pouvez terminer avec les autres requêtes. Astuce: assurez-vous que col1 / col2 / col3 possède des indices de regroupement par.la source
J'ai pensé partager ma solution car elle fonctionne dans des circonstances particulières. Dans mon cas, la table avec des valeurs en double n'avait pas de clé étrangère (car les valeurs ont été dupliquées à partir d'une autre base de données).
PS: lorsque je travaille sur des choses comme ça, j'utilise toujours une transaction, cela garantit non seulement que tout est exécuté dans son ensemble, mais me permet également de tester sans risquer quoi que ce soit. Mais bien sûr, vous devriez quand même faire une sauvegarde juste pour être sûr ...
la source
Cette requête a montré de très bonnes performances pour moi:
il a supprimé 1M lignes en un peu plus de 30sec d'une table de 2M (50% de doublons)
la source
Utilisation de CTE. L'idée est de joindre sur une ou plusieurs colonnes qui forment un enregistrement en double, puis de supprimer celui que vous aimez:
la source
Encore une autre solution simple peut être trouvée sur le lien collé ici . Celui-ci est facile à saisir et semble être efficace pour la plupart des problèmes similaires. C'est pour SQL Server mais le concept utilisé est plus qu'acceptable.
Voici les parties pertinentes de la page liée:
Considérez ces données:
Alors, comment pouvons-nous supprimer ces données en double?
Tout d'abord, insérez une colonne d'identité dans cette table en utilisant le code suivant:
Utilisez le code suivant pour le résoudre:
la source
ROW_NUMBER
version fonctionne très bien dans ce cas sans avoir à aller jusqu'à ajouter une nouvelle colonne avant de commencer.Voici un autre bon article sur la suppression des doublons .
Il explique pourquoi il est difficile: " SQL est basé sur l'algèbre relationnelle, et les doublons ne peuvent pas se produire dans l'algèbre relationnelle, car les doublons ne sont pas autorisés dans un ensemble. "
La solution de table temporaire et deux exemples mysql.
À l'avenir, allez-vous l'empêcher au niveau de la base de données ou du point de vue de l'application. Je suggérerais le niveau de la base de données car votre base de données devrait être responsable du maintien de l'intégrité référentielle, les développeurs causeront juste des problèmes;)
la source
Oh, bien sûr. Utilisez une table temporaire. Si vous voulez une seule déclaration peu performante qui "fonctionne", vous pouvez aller avec:
Fondamentalement, pour chaque ligne du tableau, la sous-sélection trouve le RowID supérieur de toutes les lignes qui sont exactement comme la ligne considérée. Vous vous retrouvez donc avec une liste de RowID qui représentent les lignes "d'origine" non dupliquées.
la source
J'avais une table où j'avais besoin de conserver les lignes non dupliquées. Je ne suis pas sûr de la vitesse ou de l'efficacité.
la source
HAVING COUNT(*) > 1
?Utilisez ceci
la source
L'autre méthode consiste à créer une nouvelle table avec les mêmes champs et avec un index unique . Déplacez ensuite toutes les données de l'ancienne table vers la nouvelle table . SQL SERVER ignore automatiquement (il y a aussi une option sur ce qu'il faut faire s'il y aura une valeur en double: ignorer, interrompre ou sth) les valeurs en double. Nous avons donc la même table sans lignes en double. Si vous ne voulez pas d'index unique, après le transfert des données, vous pouvez le supprimer .
Surtout pour les tables plus grandes, vous pouvez utiliser DTS (package SSIS pour importer / exporter des données) afin de transférer toutes les données rapidement vers votre nouvelle table indexée de manière unique. Pour 7 millions de lignes, cela ne prend que quelques minutes.
la source
En utilisant la requête ci-dessous, nous pouvons supprimer les enregistrements en double sur la base d'une seule colonne ou de plusieurs colonnes. la requête ci-dessous est en train de supprimer sur la base de deux colonnes. le nom de la table est:
testing
et les noms des colonnesempno,empname
la source
Créer un nouveau tableau vierge avec la même structure
Exécuter une requête comme celle-ci
Exécutez ensuite cette requête
la source
C'est le moyen le plus simple de supprimer un enregistrement en double
http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105
la source
Je mentionnerais cette approche aussi bien qu'elle peut être utile et fonctionne dans tous les serveurs SQL: assez souvent, il n'y a qu'un ou deux doublons, et les identifiants et le nombre de doublons sont connus. Dans ce cas:
la source
Je ne sais pas à quel point cela fonctionnerait, mais je pense que vous pouvez écrire un déclencheur pour appliquer cela, même si vous ne pouvez pas le faire directement avec un index. Quelque chose comme:
De plus, varchar (2048) me semble louche (certaines choses dans la vie font 2048 octets, mais c'est assez rare); cela ne devrait-il vraiment pas être varchar (max)?
la source
Une autre façon de le faire: -
la source
la source
la source
Si vous souhaitez prévisualiser les lignes que vous êtes sur le point de supprimer et garder le contrôle sur les lignes en double à conserver. Voir http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/
la source