次の例では、T-SQLを使用して、主キーまたは一意の識別子の列を無視しながら、SQLServerの重複する行を削除します。
より具体的には、例では重複する行を削除しますが、1つは保持します。したがって、2つの同一の行が与えられると、1つは削除され、もう1つは残ります。これは、テーブルの「重複排除」、テーブルの「重複排除」などと呼ばれることがよくあります。
サンプルデータ
次のデータを含むテーブルがあるとします。
SELECT * FROM Dogs;
結果:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +---------+-------------+------------+
最初の2行が重複しており、最後の3行も重複していることがわかります。
オプション1
まず、次のコードを実行して、重複排除される行を確認しましょう。
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
SELECT * FROM cte WHERE Row_Number <> 1;
結果:
+---------+-------------+------------+--------------+ | DogId | FirstName | LastName | Row_Number | |---------+-------------+------------+--------------| | 2 | Bark | Smith | 2 | | 6 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | +---------+-------------+------------+--------------+
ROW_NUMBER()
を使用しました PARTITION BY
で機能する 重複が見つかった場合は増分し、重複していないものが見つかった場合はリセットする独自の行番号を作成する句。 1より大きい数値は重複していることを示しているため、1より大きい数値のみを返します。
このテーブルの重複排除を行うと、3つの行が削除されることがわかります。
それでは、テーブルの複製を解除しましょう:
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
DELETE FROM cte WHERE Row_Number <> 1;
結果:
(3 rows affected)
予想どおり、3行が削除されました。
このクエリは前のクエリとほとんど同じです。 SELECT *
を変更するだけでした DELETE
の最後の行 。
次に、正しい行が削除されたことを確認するために、テーブルからすべての行を選択しましょう。
SELECT * FROM Dogs;
結果:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +---------+-------------+------------+
各犬がテーブルに1回だけ表示されるようになっていることがわかります。
オプション2
前の例の後にテーブルが復元されたと仮定して、重複をチェックする別の方法を次に示します。
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
結果:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 2 | Bark | Smith | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +---------+-------------+------------+
この場合、EXCEPT
を使用しました 演算子とMIN()
働き。 MIN()
を置き換えることができます MAX()
を使用 削除する行によって異なります。
行を削除するには、SELECT *
を置き換えるだけです。 DELETE
を使用 :
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
結果:
(3 rows affected)
そして、残っているものを確認してください:
SELECT * FROM Dogs;
結果:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +---------+-------------+------------+
オプション3
それを行う別の方法は、テーブル自体を結合し、その方法で重複をチェックすることです。
前の例の後にテーブルが復元されたと仮定すると、重複を選択するための3番目のオプションは次のとおりです。
SELECT *
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId = (
SELECT MAX(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
);
結果:
+---------+-------------+------------+---------+-------------+------------+ | DogId | FirstName | LastName | DogId | FirstName | LastName | |---------+-------------+------------+---------+-------------+------------| | 2 | Bark | Smith | 1 | Bark | Smith | | 7 | Wag | Johnson | 5 | Wag | Johnson | | 7 | Wag | Johnson | 6 | Wag | Johnson | +---------+-------------+------------+---------+-------------+------------+
この結果は前の例の結果ほど明確ではありませんが、どの行が重複しているかはわかります。
これで、重複する行を削除するようにそのクエリを変更できます。
DELETE FROM Dogs WHERE DogId IN (
SELECT d2.DogId
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId=(
SELECT MAX(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
)
);
結果:
(3 rows affected)
もう一度、3つの行が削除されました。
表をもう一度確認しましょう:
SELECT * FROM Dogs;
結果:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 7 | Wag | Johnson | +---------+-------------+------------+
今回は他の行が削除されていることに気付くかもしれません。つまり、DogId
ができました。 ■2、3、4、および7ですが、前の例では1、3、4、および5が残っています。
この例を簡単に変更して、前の例と同じ行を削除できます。これを行うには、MIN()
を使用できます MAX()
の代わりに関数 機能:
DELETE FROM Dogs WHERE DogId IN (
SELECT d2.DogId
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId=(
SELECT MIN(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
)
);