Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie lösche ich doppelte Zeilen in SQL Server 2008?

Am einfachsten geht das mit einem CTE (Common Table Expression). Ich verwende diese Methode, wenn ich Rohdaten importieren muss; Das erste, was ich tue, um es zu bereinigen, ist sicherzustellen, dass es keine Duplikate gibt – dass ich eine Art eindeutiges Handle für jede Zeile habe.

Zusammenfassung:

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY [dupe-column-list] ORDER BY [dupe-column-list]) AS _dupe_num FROM [table-name] WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

Im Teil "dupe-column-list" listen Sie alle beteiligten Spalten auf, in denen Sie möchten, dass die Werte eindeutig sind. Bei ORDER BY entscheiden Sie innerhalb einer Reihe von Duplikaten, welche Zeile "gewinnt" und welche gelöscht wird. (Das "WHERE 1=1" ist nur eine persönliche Gewohnheit.)

Der Grund dafür ist, dass Sql Server einen internen, eindeutigen Verweis auf jede Quellzeile behält, die im CTE ausgewählt ist. Wenn also DELETE ausgeführt wird, kennt es die genaue Zeile, die gelöscht werden soll, unabhängig davon, was Sie in die Auswahlliste Ihres CTE eingegeben haben. (Wenn Sie nervös sind, können Sie "DELETE" in "SELECT *" ändern, aber da Sie doppelte Zeilen haben, wird es nicht helfen; wenn Sie jede Zeile eindeutig identifizieren könnten, würden Sie dies nicht lesen .)

Beispiel:

CREATE TABLE ##_dupes (col1 int, col2 int, col3 varchar(50));
INSERT INTO ##_dupes 
    VALUES (1, 1, 'one,one')
        , (2, 2, 'two,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, 'one,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, '1,2');

Von den 8 Reihen haben Sie 5 mit doppelten Problemen zu tun; 3 Zeilen müssen entfernt werden. Sie können die Probleme damit sehen:

SELECT col1
    , col2
    , col3
    , COUNT(1) AS _total 
    FROM ##_dupes 
    WHERE 1=1 
    GROUP BY col1, col2, col3
    HAVING COUNT(1) > 1
    ORDER BY _total DESC;

Führen Sie nun die folgende Abfrage aus, um die Duplikate zu entfernen, wobei 1 Zeile aus jedem Satz von Duplikaten übrig bleibt.

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY col1, col2, col3 ORDER BY col1, col2, col3) AS _dupe_num FROM ##_dupes WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

Sie haben jetzt 5 Zeilen, von denen keine dupliziert wird.