Frage Wie kann ich doppelte Zeilen entfernen?


Was ist der beste Weg, doppelte Zeilen von einem ziemlich großen zu entfernen SQL Server Tabelle (d. h. 300.000+ Zeilen)?

Die Zeilen werden natürlich wegen der Existenz der RowID Identitätsfeld

Mein Tisch

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


Ursprung


Antworten:


Nullen vorausgesetzt, du GROUP BY die einzigartigen Spalten und SELECT das MIN (or MAX) RowId als die zu behaltende Zeile. Löschen Sie dann einfach alles, was keine Zeilen-ID hatte:

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

Falls Sie eine GUID anstelle einer Ganzzahl haben, können Sie sie ersetzen

MIN(RowId)

mit

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

1062
2017-08-20 22:00



Eine andere Möglichkeit, dies zu tun ist

; 

--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;

ich benutze ORDER BY (SELECT 0) oben, da es willkürlich ist, welche Reihe im Falle eines Unentschiedens zu bewahren ist.

Um das neueste in zu erhalten RowID Bestellen Sie zum Beispiel könnten Sie verwenden ORDER BY RowID DESC 

Ausführungspläne

Der Ausführungsplan dafür ist oft einfacher und effizienter als der in der akzeptierten Antwort, da er den Self-Join nicht erfordert.

Execution Plans

Dies ist jedoch nicht immer der Fall. Ein Ort, wo die GROUP BY Lösung könnte bevorzugt werden Situationen, in denen a Hash-Aggregat würde vor einem Stromaggregat bevorzugt werden.

Das ROW_NUMBER Lösung wird immer so ziemlich den gleichen Plan geben, während die GROUP BY Strategie ist flexibler.

Execution Plans

Faktoren, die den Hash-Aggregat-Ansatz bevorzugen könnten, wären

  • Kein nützlicher Index für die Partitionierungsspalten
  • relativ wenige Gruppen mit relativ mehr Duplikaten in jeder Gruppe

In extremen Versionen dieses zweiten Falls (wenn es nur sehr wenige Gruppen mit vielen Duplikaten gibt) könnte man auch in Erwägung ziehen, einfach die Zeilen einzufügen, um sie dann in einer neuen Tabelle zu behalten TRUNCATE- das Original kopieren und zurückkopieren, um die Protokollierung im Vergleich zum Löschen eines sehr hohen Anteils der Zeilen zu minimieren.


700
2017-09-29 14:52



Es gibt einen guten Artikel darüber Entfernen von Duplikaten auf der Microsoft Support-Website. Es ist ziemlich konservativ - sie haben alles in getrennten Schritten - aber es sollte gut gegen große Tabellen funktionieren.

Ich habe in der Vergangenheit Self-Joins verwendet, obwohl es wahrscheinlich mit einer HAVING-Klausel versehen werden könnte:

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



Die folgende Abfrage ist nützlich, um doppelte Zeilen zu löschen. Die Tabelle in diesem Beispiel hat ID als Identitätsspalte und die Spalten, die doppelte Daten haben, sind Column1, Column2 und 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) 

Das folgende Skript zeigt die Verwendung von GROUP BY, HAVING, ORDER BY in einer Abfrage und gibt die Ergebnisse mit der doppelten Spalte und ihrer Anzahl zurück.

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



Dadurch werden doppelte Zeilen mit Ausnahme der ersten Zeile gelöscht

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

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


36
2017-09-10 13:07



Ich würde CTE bevorzugen, um doppelte Reihen von der sql-Servertabelle zu löschen

empfehlen dringend diesen Artikel zu folgen ::http://dotnetmob.com/sql-server-article/delete-duplicate-rows-in-sql-server/

indem man das Original bewahrt

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

ohne das Original zu behalten

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



Schnell und schmutzig, um exakt duplizierte Zeilen zu löschen (für kleine Tabellen):

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

21
2018-02-05 21:44