2010-08-07 5 views

Répondre

4
  1. Faire une requête A que vous obtient les lignes qui se qualifient comme des doublons
  2. Faire un B requête que vous obtient les lignes que vous souhaitez conserver
  3. Faire une requête qui supprime toutes les lignes qui sont en mais pas dans B.

Exemple.

En supposant une table nommée table, avec une colonne d'identité autoincrement nommé id et une colonne nommée name dont vous voulez supprimer les doubles. De chaque nom, vous voulez conserver l'enregistrement le plus ancien (celui avec l'ID le plus bas).

la requête A ressemble alors quelque chose comme:

SELECT * FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 

la requête B serait:

SELECT * FROM table 
WHERE id IN (SELECT min(id) FROM table GROUP BY name) 

Maintenant, combinons ces pour former la requête de suppression:

DELETE FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 
AND NOT id IN (SELECT min(id) FROM table GROUP BY name) 

Dans l'exemple À la main, vous pouvez omettre la première requête, mais quand les choses se compliquent, c'est une bonne sauvegarde supplémentaire.

1

Vous ne pouvez pas. Les enregistrements entièrement dupliqués (ceux qui ont tous les champs égaux) ne peuvent pas être supprimés par un, car vous ne pouvez pas les différencier dans une clause Where dans une requête de suppression.
La seule manière serait de faire une requête select distinct pour sélectionner toutes les lignes sans doublons, puis les insérer dans une table vide.

Si vous ne disposez pas des enregistrements entièrement en double, la question est formulée de manière incorrecte, et vous ne voulez pas supprimer les doublons, car il n'y en a pas. Les lignes qui ont un ensemble incomplet de champs égaux ne sont pas des doublons. Dans ce cas, vous voudrez supprimer les lignes qui ont des champs égaux, auquel cas vous devrez spécifier ceux à laisser si un certain champ ou jeu de champs n'est pas égal.

+0

Je ne pense pas que ce soit vrai. Supposons que vous sélectionnez tout d'une table, plus une colonne ROW_NUMBER(). Les lignes seront retournées dans l'ordre de l'index clusterisé, et vous obtiendrez une valeur de numéro de ligne différente pour chacun d'eux. Vous pourriez alors l'utiliser pour différencier les doublons dans une clause WHERE. – Yellowfog

+0

row_number est une fonction qui fonctionne avec une instruction order by, qui n'est autorisée que dans une requête select. C'est juste une des raisons pour lesquelles row_number ne peut pas participer directement à une instruction delete. L'une des solutions que j'ai trouvées sur Internet consistait à créer une table séparée, en introduisant row_number comme nouveau champ, puis à exécuter l'instruction delete. Ce n'est pas ce que l'auteur veut. – AlexanderMP

0

Vous pouvez le faire sans problème en utilisant une expression de table commune (CTE), vous n'avez pas besoin d'utiliser des tables temporaires du tout. Faites juste attention si la suppression va contre une table à trafic élevé. La suppression de grandes quantités de données peut provoquer un blocage et un blocage, le journal de transfert sera également touché.

Remarque: Ce code a été écrit sans test, mais devrait fonctionner (SQL 2005 et versions ultérieures).

/* Create test data with duplicates */ 
declare @TestTable Table (Col1 int) 

insert into @TestTable 

select 1 union all 
select 1 union all 
select 2 union all 
select 3 union all 
select 3 union all 
select 4 
; 
/* Create CTE to number all duplicates (gives a running number to all identical values in Col1) */ 
with FindDupes as 
(
Select Col1,ROW_NUMBER() over (partition by Col1 order by Col1) RN 

from @TestTable 
) 
/* Delete the duplicates (anything that has a higher rownumber than one) */ 
Delete from FindDupes where RN>1 
; 

/* Select the remaining data from the table */ 
Select * from @TestTable 
-1

Je pense que cette requête fonctionne correctement:

delete from table where id in (select count(*)c from table group by id having c > 1) 
schéma
Questions connexes