sql >> データベース >  >> RDS >> Sqlserver

SQLServerで重複行をチェックする4つの方法

    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行も重複していることがわかります。

    オプション1

    次のクエリを使用して、重複する行に関する情報を返すことができます。

    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       |
    +-----------+-----------+---------+
    オプション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       |
    +---------+-----------+-----------+---------+
    > オプション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から始まります)。

    オプション4

    一致する重複からの余剰行のみを返す場合は、次のように、上記のクエリを一般的なテーブル式として使用できます。

    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;

    1. AndroidでProguardとSQLcipherを使用しようとしているときにNoClassDefFoundErrorを取得する

    2. Oracle:サブクエリ内の複数の結果を1つのコンマ区切り値に結合します

    3. サブクエリと相関サブクエリの違い

    4. PostgreSQL DESCRIBE TABLE