最も簡単な方法は、CTE (共通テーブル式) を使用することです。インポートする生データがある場合は、この方法を使用します。サニタイズするために最初に行うことは、重複がないことを確認することです---各行に何らかの一意のハンドルがあることを確認します.
概要:
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;
「dupe-column-list」部分は、値が一意である必要がある関連するすべての列をリストする場所です。 ORDER BY は、一連の重複の中で、どの行が「優先」され、どの行が削除されるかを決定する場所です。 (「WHERE 1=1」は個人的な習慣です。)
これが機能する理由は、Sql Server が CTE で選択された各ソース行への内部の一意の参照を保持しているためです。したがって、DELETE が実行されると、CTE の選択リストに何を入れても、削除する正確な行を認識します。 (緊張している場合は、「DELETE」を「SELECT *」に変更できますが、行が重複しているため、役に立ちません。各行を一意に識別できれば、これを読んでいないでしょう。 .)
例:
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');
8 行のうち、5 行が重複した問題に関係しています。 3 行を削除する必要があります。これで問題を確認できます:
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;
次のクエリを実行して重複を削除し、重複の各セットから 1 行を残します。
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;
これで 5 つの行が残りますが、重複しているものはありません。