une - supprimer doublons sql




Comment puis-je supprimer les lignes dupliquées dans une table (9)

Ajoutez une colonne d'identité pour agir en tant que clé primaire de remplacement, et utilisez-la pour identifier deux des trois lignes à supprimer.

J'envisagerais de laisser la colonne d'identité en place par la suite, ou s'il s'agit d'une sorte de table de liens, créez une clé primaire composée sur les autres colonnes.

J'ai une table avec disons 3 colonnes. Il n'y a pas de clé primaire, donc il peut y avoir des lignes en double. Je dois juste en garder un et supprimer les autres. Une idée de comment faire est Sql Server?


Après avoir nettoyé le désordre actuel, vous pouvez ajouter une clé primaire qui inclut tous les champs de la table. Cela vous empêchera de retourner dans le pétrin. Bien sûr, cette solution pourrait très bien casser le code existant. Cela devra aussi être géré.


Je ne suis pas sûr si cela fonctionne avec les instructions DELETE, mais c'est un moyen de trouver des lignes en double:

 SELECT *
 FROM myTable t1, myTable t2
 WHERE t1.field = t2.field AND t1.id > t2.id

Je ne suis pas sûr si vous pouvez simplement changer le "SELECT" à un "SUPPRIMER" (quelqu'un veut me le faire savoir?) , Mais même si vous ne pouvez pas, vous pourriez juste le faire dans une sous-requête.


Je sélectionnerais DISTINCT les rangées et les jetterais dans une table temporaire, alors déposez la table de source et recopiez les données du temp. EDIT: maintenant avec un extrait de code!

INSERT INTO TABLE_2 
SELECT DISTINCT * FROM TABLE_1
GO
DELETE FROM TABLE_1
GO
INSERT INTO TABLE_1
SELECT * FROM TABLE_2
GO

Pouvez-vous ajouter un champ d'identité de clé primaire à la table?


Voici une autre façon, avec des données de test

create table #table1 (colWithDupes1 int, colWithDupes2 int)
insert into #table1
(colWithDupes1, colWithDupes2)
Select 1, 2 union all
Select 1, 2 union all
Select 2, 2 union all
Select 3, 4 union all
Select 3, 4 union all
Select 3, 4 union all
Select 4, 2 union all
Select 4, 2 


select * from #table1

set rowcount 1
select 1

while @@rowcount > 0
delete #table1  where 1 < (select count(*) from #table1 a2 
   where #table1.colWithDupes1 = a2.colWithDupes1
and #table1.colWithDupes2 = a2.colWithDupes2
)

set rowcount 0

select * from #table1

Qu'en est-il de cette solution:

D'abord, vous exécutez la requête suivante:

  select 'set rowcount ' + convert(varchar,COUNT(*)-1) + ' delete from MyTable where field=''' + field +'''' + ' set rowcount 0'  from mytable group by field having COUNT(*)>1

Et puis vous avez juste à exécuter le jeu de résultats renvoyé

set rowcount 3 delete from Mytable where field='foo' set rowcount 0
....
....
set rowcount 5 delete from Mytable where field='bar' set rowcount 0

J'ai traité le cas quand vous avez une seule colonne, mais il est assez facile d'adapter la même approche à une colonne. Faites-moi savoir si vous voulez que je publie le code.


L'exemple suivant fonctionne également lorsque votre PK est juste un sous-ensemble de toutes les colonnes de la table.

(Note: J'aime l'approche avec l'insertion d'une autre colonne de substitution, mais peut-être que cette solution est également utile.)

Trouvez d'abord les lignes en double:

SELECT col1, col2, count(*)
FROM t1
GROUP BY col1, col2
HAVING count(*) > 1

S'il n'y en a que peu, vous pouvez les supprimer manuellement:

set rowcount 1
delete from t1
where col1=1 and col2=1

La valeur de "rowcount" devrait être n-1 fois le nombre de doublons. Dans cet exemple, il y a 2 dulpicates, donc rowcount vaut 1. Si vous obtenez plusieurs lignes dupliquées, vous devez le faire pour chaque clé primaire unique.

Si vous avez beaucoup de doublons, copiez chaque clé une fois dans une autre table:

SELECT col1, col2, col3=count(*)
INTO holdkey
FROM t1
GROUP BY col1, col2
HAVING count(*) > 1

Puis copiez les clés, mais éliminez les doublons.

SELECT DISTINCT t1.*
INTO holddups
FROM t1, holdkey
WHERE t1.col1 = holdkey.col1
AND t1.col2 = holdkey.col2

Dans vos clés, vous avez maintenant des clés uniques. Vérifiez si vous n'obtenez aucun résultat:

SELECT col1, col2, count(*)
FROM holddups
GROUP BY col1, col2

Supprimez les doublons de la table d'origine:

DELETE t1
FROM t1, holdkey
WHERE t1.col1 = holdkey.col1
AND t1.col2 = holdkey.col2

Insérez les lignes d'origine:

INSERT t1 SELECT * FROM holddups

btw et pour l'exhaustivité: Dans Oracle, il existe un champ masqué que vous pouvez utiliser (rowid):

DELETE FROM our_table
WHERE rowid not in
(SELECT MIN(rowid)
FROM our_table
GROUP BY column1, column2, column3... ;

voir: Microsoft Knowledge Site


Voici la méthode que j'ai utilisée quand j'ai posé cette question -

DELETE MyTable 
FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL




database