sql >> Database >  >> RDS >> Sqlserver

Hoe dubbele rijen in SQL Server 2008 te verwijderen?

De eenvoudigste manier is met een CTE (common table expression). Ik gebruik deze methode wanneer ik onbewerkte gegevens moet importeren; het eerste wat ik doe om het te ontsmetten, is ervoor te zorgen dat er geen duplicaten zijn --- dat ik een soort uniek handvat voor elke rij heb.

Samenvatting:

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;

In het gedeelte "dupe-column-list" vermeldt u alle betrokken kolommen waarvan u wilt dat de waarden uniek zijn. De ORDER BY is waar u beslist, binnen een reeks duplicaten, welke rij "wint" en welke wordt verwijderd. (De "WHERE 1=1" is slechts een persoonlijke gewoonte.)

De reden dat het werkt, is omdat Sql Server een interne, unieke verwijzing bewaart naar elke bronrij die is geselecteerd in de CTE. Dus wanneer de DELETE wordt uitgevoerd, weet deze de exacte rij die moet worden verwijderd, ongeacht wat u in de selectielijst van uw CTE plaatst. (Als je nerveus bent, zou je de "VERWIJDEREN" kunnen veranderen in "SELECTEER *", maar aangezien je dubbele rijen hebt, zal het niet helpen; als je elke rij uniek zou kunnen identificeren, zou je dit niet lezen .)

Voorbeeld:

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

Van de 8 rijen zijn er 5 betrokken bij dubbele problemen; 3 rijen moeten worden verwijderd. Je kunt de problemen hiermee zien:

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;

Voer nu de volgende query uit om de duplicaten te verwijderen, waarbij u 1 rij overhoudt van elke set duplicaten.

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;

U houdt nu 5 rijen over, waarvan geen enkele is gedupliceerd.



  1. PHP Controleer of string een letter bevat

  2. REgex om numeriek uit string in orakel te halen

  3. Fatale fout opgetreden tijdens het uitvoeren van de opdracht. mysql-connector .net

  4. Hoe werken vensterfuncties en de group by-clausule op elkaar in?