A maneira mais simples é com um CTE (expressão de tabela comum). Eu uso esse método quando tenho dados brutos para importar; a primeira coisa que faço para sanitizá-lo é garantir que não haja duplicatas --- que tenho algum tipo de identificador exclusivo para cada linha.
Resumo:
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;
A parte "dupe-column-list" é onde você lista todas as colunas envolvidas onde você deseja que os valores sejam únicos. O ORDER BY é onde você decide, dentro de um conjunto de duplicatas, qual linha "ganha" e qual é excluída. (O "WHERE 1=1" é apenas um hábito pessoal.)
A razão pela qual funciona é porque o Sql Server mantém uma referência interna exclusiva para cada linha de origem selecionada no CTE. Portanto, quando o DELETE é executado, ele sabe a linha exata a ser excluída, independentemente do que você colocar na lista de seleção do seu CTE. (Se você está nervoso, você pode alterar o "DELETE" para "SELECT *", mas como você tem linhas duplicadas, não vai ajudar; se você pudesse identificar exclusivamente cada linha, você não estaria lendo isso .)
Exemplo:
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');
Das 8 linhas, você tem 5 envolvidas com problemas duplicados; 3 linhas precisam ser removidas. Você pode ver os problemas com isso:
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;
Agora execute a seguinte consulta para remover as duplicatas, deixando 1 linha de cada conjunto de duplicatas.
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;
Agora você tem 5 linhas, nenhuma das quais está duplicada.