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

PostgreSQLで重複する行を選択する4つの方法

    PostgreSQLに重複する行があるテーブルがある場合は、次のクエリのいずれかを使用して重複する行を返すことができます。

    サンプルデータ

    次のデータを含むテーブルがあるとします。

    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行は重複しています。これは、3つの列すべてに、重複する各行に同じ値が含まれているためです。

    オプション1

    次のクエリを使用して、重複している行の数を確認できます。

    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

    または、カウントの降順で並べ替えて、重複が最も多い行が最初に表示されるようにすることもできます。

    SELECT 
        PetId,
        PetName,
        PetType,
        COUNT(*) AS "Count"
    FROM Pets
    GROUP BY 
        PetId,
        PetName,
        PetType
    ORDER BY Count(*) DESC;

    結果:

     petid | petname | pettype | Count 
    -------+---------+---------+-------
         4 | Bark    | Dog     |     3
         1 | Wag     | Dog     |     2
         2 | Scratch | Cat     |     1
         3 | Tweet   | Bird    |     1
    オプション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

    もう1つのオプションは、PostgresのROW_NUMBER()を使用することです。 ウィンドウ関数:

    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. 複合キーを使用したWHERE_INクエリ?

    2. 実行方法によっては、Oracleストアドプロシージャの実行時間が大幅に増加するのはなぜですか?

    3. MySQLを使用した大規模な結果セットのストリーミング

    4. Oracle 11gの選択クエリにオフセットを追加するにはどうすればよいですか?