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

Oracleで重複行を選択する6つの方法

    次の例は、Oracleデータベーステーブルから重複する行を返します。

    サンプルデータ

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

    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行も重複しています。この場合、重複する行には、ID列を含むすべての列で重複する値が含まれます。

    オプション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

    行をすべての列でグループ化し、各グループの行数を返しました。カウントが1より大きい行は重複しています。

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

    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を使用できます。 カウントが1より大きい行のみを返す句

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

    結果:

    PETID	PETNAME	PETTYPE	Count
    4	Bark	Dog	3
    1	Wag	Dog	2
    オプション3

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

    SELECT 
        PetId,
        PetName,
        PetType,
        ROW_NUMBER() OVER ( 
            PARTITION BY PetId, PetName, PetType 
            ORDER BY PetId, PetName, PetType
            ) AS rn
    FROM Pets;

    結果:

    PETID	PETNAME	PETTYPE	RN
    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 
                PetId,
                PetName,
                PetType,
                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

    これにより、一致する重複から余分な行だけが返されます。したがって、同じ行が2つある場合は、そのうちの1つを返します。同一の行が3つある場合は、2つを返します。

    オプション5

    テーブルに主キー列が含まれていない場合、Oracleのrowidを利用できます。 疑似列:

    SELECT * FROM Pets
    WHERE EXISTS (
      SELECT 1 FROM Pets p2 
      WHERE Pets.PetName = p2.PetName
      AND Pets.PetType = p2.PetType
      AND Pets.rowid > p2.rowid
    );

    結果:

    PETID	PETNAME	PETTYPE
    1	Wag	Dog
    4	Bark	Dog
    4	Bark	Dog

    これが機能する方法は、Oracleデータベースの各行にrowidがあります。 行のアドレスを返す疑似列。 rowid はテーブル内の行の一意の識別子であり、通常、その値はデータベース内の行を一意に識別します。ただし、同じクラスターに一緒に格納されている異なるテーブルの行は、同じrowidを持つ可能性があることに注意してください。 。

    上記の例の利点の1つは、SELECT *を置き換えることができることです。 DELETEを使用 テーブルの複製を解除するため。

    オプション6

    そして最後に、rowidを使用する別のオプションがあります 疑似列:

    SELECT * FROM Pets
    WHERE rowid > (
      SELECT MIN(rowid) FROM Pets p2  
      WHERE Pets.PetName = p2.PetName
      AND Pets.PetType = p2.PetType
    );

    結果:

    PETID	PETNAME	PETTYPE
    1	Wag	Dog
    4	Bark	Dog
    4	Bark	Dog

    前の例と同じ結果です。

    前の例と同様に、SELECT *を置き換えることができます DELETEを使用 テーブルから重複する行を削除するため。


    1. 初心者向けのSQL以下(=)演算子

    2. PostgreSQLユーザーパスワードを変更するにはどうすればよいですか?

    3. MySQLで重複する値を見つける

    4. SQLiteエラーに複数の行を挿入します(エラーコード=1)