SQLServerで重複する行を見つけるために使用できる4つの方法を次に示します。
「重複行」とは、すべての列でまったく同じ値を共有する2つ以上の行を意味します。
次のデータを含むテーブルがあるとします。
SELECT * FROM Pets;
結果:
+---------+-----------+-----------+ | PetId | PetName | PetType | |---------+-----------+-----------| | 1 | Wag | Dog | | 1 | Wag | Dog | | 2 | Scratch | Cat | | 3 | Tweet | Bird | | 4 | Bark | Dog | | 4 | Bark | Dog | | 4 | Bark | Dog | +---------+-----------+-----------+
最初の2行は重複しており、最後の3行も重複していることがわかります。
次のクエリを使用して、重複する行に関する情報を返すことができます。
SELECT
DISTINCT PetId,
COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;
結果:
+---------+---------+ | PetId | Count | |---------+---------| | 1 | 2 | | 2 | 1 | | 3 | 1 | | 4 | 3 | +---------+---------+
SELECT
を展開できます 必要に応じて列を追加するリスト:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
結果:
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+>
テーブルに一意の識別子がある場合は、その列をクエリから削除するだけです。たとえば、PetId
columnは、実際には一意のIDを含む主キー列です。次のクエリを実行して、主キー列をカウントせずに、重複するすべての行を返すことができます。
SELECT
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetName,
PetType
ORDER BY PetName;
結果:
+-----------+-----------+---------+ | PetName | PetType | Count | |-----------+-----------+---------| | Bark | Dog | 3 | | Scratch | Cat | 1 | | Tweet | Bird | 1 | | Wag | Dog | 2 | +-----------+-----------+---------+
実際の重複行のみを返したい場合は、HAVING
を追加できます。 条項:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY PetId;
結果:
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+>
これを行う別の方法は、ROW_NUMBER()
を使用することです。 PARTITION BY
で機能する 結果セットの出力に番号を付ける句。
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
結果:
+---------+-----------+-----------+--------------+ | PetId | PetName | PetType | Row_Number | |---------+-----------+-----------+--------------| | 1 | Wag | Dog | 1 | | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 1 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+--------------+
PARTITION BY
句は、FROM
によって生成された結果セットを分割します 関数が適用されるパーティションへの句。結果セットにパーティションを指定すると、各パーティションによって番号付けが最初からやり直されます(つまり、各パーティションの最初の行の番号付けは1から始まります)。
一致する重複からの余剰行のみを返す場合は、次のように、上記のクエリを一般的なテーブル式として使用できます。
WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets
)
SELECT * FROM CTE WHERE Row_Number <> 1;
結果:
+---------+-----------+-----------+--------------+ | PetId | PetName | PetType | Row_Number | |---------+-----------+-----------+--------------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+--------------+
これを行う利点の1つは、SELECT *
を切り替えるだけで重複行を削除できることです。 DELETE
へ (最後の行)。
したがって、上記のコードを使用して、削除される行を確認し、正しい行を削除することに同意したら、それをDELETE
に切り替えることができます。 実際にそれらを削除するステートメント。
このように:
WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets
)
DELETE FROM CTE WHERE Row_Number <> 1;