T-SQL: usunięcie wszystkich zduplikowanych wierszy, ale zachowanie jednego [duplikat]

Możliwy duplikat:
SQL - Jak mogę usunąć zduplikowane wiersze?

Mam tabelę z bardzo dużą ilością wierszy. Duplikaty nie są dozwolone, ale ze względu na problem z tworzeniem wierszy wiem, że w tej tabeli znajdują się duplikaty. Muszę wyeliminować dodatkowe wiersze z perspektywy kluczowych kolumn. Niektóre inne kolumny mogą mieć nieco inne dane, ale mnie to nie obchodzi. Muszę jeszcze zatrzymać jedną z te rzędy jednak. SELECT DISTINCT nie będzie działać, ponieważ działa na wszystkich kolumnach i muszę tłumić duplikaty na podstawie kolumn kluczowych.

Jak mogę usunąć dodatkowe wiersze, ale nadal skutecznie je zachować?

Author: Community, 2011-05-17

3 answers

Nie powiedziałeś, jakiej wersji używasz, ale w SQL 2005 i nowszych możesz użyć wspólnego wyrażenia tabeli z klauzulą OVER . Idzie trochę tak:

WITH cte AS (
  SELECT[foo], [bar], 
     row_number() OVER(PARTITION BY foo, bar ORDER BY baz) AS [rn]
  FROM TABLE
)
DELETE cte WHERE [rn] > 1
Pobaw się nim i zobacz, na co cię stać.

(Edit: aby być pomocnym, ktoś edytował klauzulę ORDER BY w CTE. Aby było jasne, możesz zamówić wszystko, co chcesz, nie musi to być jedna z kolumn zwróconych przez cte. W rzeczywistości powszechnym przypadkiem użycia jest to, że " foo, bar "to identyfikator grupy, a" baz " to jakiś znacznik czasu. Aby zachować najnowsze, wykonaj ORDER BY baz desc)

 445
Author: Ben Thul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-23 13:19:30

Przykładowe zapytanie:

DELETE FROM Table
WHERE ID NOT IN
(
SELECT MIN(ID)
FROM Table
GROUP BY Field1, Field2, Field3, ...
)

Tutaj fields są kolumny, na których chcesz pogrupować zduplikowane wiersze.

 89
Author: jams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-17 01:41:40

Oto mój zwrot na to, z runnable przykład. Uwaga będzie to działać tylko w sytuacji, gdy {[2] } jest unikalna, a wartości są zduplikowane w innych kolumnach.

DECLARE @SampleData AS TABLE (Id int, Duplicate varchar(20))

INSERT INTO @SampleData
SELECT 1, 'ABC' UNION ALL
SELECT 2, 'ABC' UNION ALL
SELECT 3, 'LMN' UNION ALL
SELECT 4, 'XYZ' UNION ALL
SELECT 5, 'XYZ'

DELETE FROM @SampleData WHERE Id IN (
    SELECT Id FROM (
        SELECT 
            Id
            ,ROW_NUMBER() OVER (PARTITION BY [Duplicate] ORDER BY Id) AS [ItemNumber]
            -- Change the partition columns to include the ones that make the row distinct
        FROM 
            @SampleData
    ) a WHERE ItemNumber > 1 -- Keep only the first unique item
)

SELECT * FROM @SampleData

I wyniki:

Id          Duplicate
----------- ---------
1           ABC
3           LMN
4           XYZ
Nie wiem, dlaczego tak pomyślałem... zdecydowanie nie najprostszy sposób, ale działa.
 20
Author: Cᴏʀʏ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-18 18:28:50