sql >> Databáze >  >> RDS >> Sqlserver

Jak odstranit duplicitní řádky v SQL Server 2008?

Nejjednodušší způsob je s CTE (common table expression). Tuto metodu používám, když mám k importu nezpracovaná data; první věc, kterou udělám, abych to dezinfikoval, je zajistit, aby tam nebyly žádné duplikáty --- že mám pro každý řádek nějakou jedinečnou rukojeť.

Shrnutí:

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;

Část "dupe-column-list" je místo, kde uvádíte všechny zahrnuté sloupce, kde chcete, aby byly hodnoty jedinečné. ORDER BY je místo, kde v rámci sady duplikátů rozhodujete, který řádek "vyhraje" a který bude smazán. (To "KDE 1=1" je jen osobní zvyk.)

Důvod, proč to funguje, je ten, že SQL Server uchovává interní, jedinečný odkaz na každý zdrojový řádek, který je vybrán v CTE. Takže když se DELETE provede, zná přesný řádek, který má být smazán, bez ohledu na to, co vložíte do výběrového seznamu vašeho CTE. (Pokud jste nervózní, můžete změnit "DELETE" na "SELECT *", ale protože máte duplicitní řádky, nepomůže to; pokud byste dokázali jedinečně identifikovat každý řádek, nečetli byste toto .)

Příklad:

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

Z 8 řádků máte 5 zapojených s duplicitními problémy; Je třeba odstranit 3 řádky. Můžete vidět problémy s tímto:

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;

Nyní spusťte následující dotaz k odstranění duplikátů a ponechejte 1 řádek z každé sady duplikátů.

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;

Nyní vám zbývá 5 řádků, z nichž žádný není duplicitní.



  1. Je MS-SQL AND/OR podmíněné (provést vyhodnocení zkratu)?

  2. Tvrzení v MySQL

  3. Získejte anonymní výsledek bloku PLSQL

  4. jedinečné omezení na datový typ Bytea na Postgresql