Question Comment puis-je supprimer les lignes en double?


Quelle est la meilleure façon de supprimer les lignes en double d'un assez grand SQL Server table (c'est-à-dire plus de 300 000 lignes)?

Les lignes, bien sûr, ne seront pas parfaites en raison de l'existence de la 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

1160
2017-08-20 21:51


origine


Réponses:


En supposant pas de null, vous GROUP BY les colonnes uniques, et SELECT la MIN (or MAX) RowId comme la ligne à conserver. Ensuite, supprimez simplement tout ce qui n'a pas d'identifiant de ligne:

DELETE 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

Si vous avez un GUID au lieu d'un entier, vous pouvez remplacer

MIN(RowId)

avec

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

1062
2017-08-20 22:00



Une autre façon possible de le faire est

; 

--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1;

j'utilise ORDER BY (SELECT 0) ci-dessus car il est arbitraire quelle rangée conserver en cas d'égalité.

Pour préserver le dernier en RowID commander par exemple vous pouvez utiliser ORDER 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.

Execution Plans

Ce n'est pas toujours le cas cependant. Un endroit où le GROUP BY solution pourrait être préférée est des situations où un agrégat de hachage serait choisi de préférence à un agrégat de flux.

le ROW_NUMBER solution donnera toujours à peu près le même plan alors que le GROUP BY la stratégie est plus flexible.

Execution Plans

Les facteurs qui pourraient favoriser l'approche de l'agrégat de hachage seraient les suivants:

  • Aucun index utile sur les colonnes de partitionnement
  • relativement moins de groupes avec relativement plus de doublons dans chaque groupe

Dans les versions extrêmes de ce second cas (s'il y a très peu de groupes avec beaucoup de doublons dans chacun), on pourrait aussi envisager simplement d'insérer les lignes pour les conserver dans une nouvelle table TRUNCATE-désigner l'original et le recopier pour minimiser la journalisation par rapport à la suppression d'une proportion très élevée des lignes.


700
2017-09-29 14:52



Il y a un bon article sur supprimer les doublons sur le site de support Microsoft. C'est assez conservateur - ils ont tout à faire en étapes séparées - mais cela devrait bien fonctionner contre les grandes tables.

J'ai utilisé des auto-jointures pour le faire dans le passé, bien que cela puisse probablement être complété par une clause HAVING:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField

132
2017-08-20 21:53



La requête suivante est utile pour supprimer les lignes en double. La table dans cet exemple a ID comme une colonne d'identité et les colonnes qui ont des données en double sont Column1, Column2 et Column3.

DELETE FROM TableName
WHERE  ID NOT IN (SELECT MAX(ID)
                  FROM   TableName
                  GROUP  BY Column1,
                            Column2,
                            Column3
                  /*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
                    nullable. Because of semantics of NOT IN (NULL) including the clause
                    below can simplify the plan*/
                  HAVING MAX(ID) IS NOT NULL) 

Le script suivant montre l'utilisation de GROUP BY, HAVING, ORDER BY dans une requête, et renvoie les résultats avec une colonne en double et son nombre.

SELECT YourColumnName,
       COUNT(*) TotalCount
FROM   YourTableName
GROUP  BY YourColumnName
HAVING COUNT(*) > 1
ORDER  BY COUNT(*) DESC 

87
2017-11-23 15:32



delete t1
from table t1, table t2
where t1.columnA = t2.columnA
and t1.rowid>t2.rowid

Postgres:

delete
from table t1
using table t2
where t1.columnA = t2.columnA
and t1.rowid > t2.rowid

52
2017-09-30 02:35



DELETE LU 
FROM   (SELECT *, 
               Row_number() 
                 OVER ( 
                   partition BY col1, col1, col3 
                   ORDER BY rowid DESC) [Row] 
        FROM   mytable) LU 
WHERE  [row] > 1 

41
2018-05-21 07:54



Cela va supprimer les lignes en double, sauf la première rangée

DELETE
FROM
    Mytable
WHERE
    RowID NOT IN (
        SELECT
            MIN(RowID)
        FROM
            Mytable
        GROUP BY
            Col1,
            Col2,
            Col3
    )

Référer (http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server)


36
2017-09-10 13:07



Je préférerais CTE pour supprimer des lignes en double de la table du serveur sql

recommande fortement de suivre cet article ::http://dotnetmob.com/sql-server-article/delete-duplicate-rows-in-sql-server/

en gardant l'original

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1

sans garder d'original

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)

22
2018-05-19 14:35



Rapide et sale pour supprimer les lignes dupliquées exactes (pour les petites tables):

select  distinct * into t2 from t1;
delete from t1;
insert into t1 select *  from t2;
drop table t2;

21
2018-02-05 21:44