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

Oracleで主キーを持つ重複行を削除する6つの方法

    これらの行に主キーまたは一意の識別子列がある場合に、OracleDatabaseの表から重複する行を削除するためのいくつかのオプションを次に示します。

    このような場合、重複する行を比較するときは主キーを無視する必要があります(主キーは一意の値を保持しているため)。

    サンプルデータ

    この例では、次のデータを使用しています。

    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    2 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン
    6 ワグ ジョンソン
    7 ワグ ジョンソン

    最初の2行は重複しており、最後の3行も重複していることがわかります。

    DogId 列は一意の値を保持しますが(テーブルの主キーであるため)、重複を比較するときにその列を無視します。主キーを含むテーブルの重複排除が必要になることがよくあるので、次の例を使用してそれを行うことができます。

    オプション1

    上記の表を重複排除するための最初のオプションは次のとおりです。

    DELETE FROM Dogs 
    WHERE DogId IN (
        SELECT DogId FROM Dogs 
        MINUS SELECT MIN(DogId) FROM Dogs 
        GROUP BY FirstName, LastName
        );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン

    重複は削除されました(ただし、各重複の1行が残っています)。

    または、 MAX()を使用することもできます MIN()の代わりに関数 削除する行を変更する関数。

    オプション2

    この例(および次の例)では、テーブルが(重複して)元の状態に復元されていると想定します。

    テーブルの重複を解除してから残りの行を選択する別の例を次に示します。

    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
        )
    );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    2 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    7 ワグ ジョンソン

    MAX()を使用したことに注意してください MIN()の代わりに関数 前の例で使用しました。これが重複排除操作に与える影響を確認できます。テーブルから別の行を削除しました。

    オプション3

    MIN()を使用する必要のないオプションは次のとおりです またはMAX()

    DELETE FROM Dogs
    WHERE EXISTS (
      SELECT 1 FROM Dogs d2 
      WHERE Dogs.FirstName = d2.FirstName
      AND Dogs.LastName = d2.LastName
      AND Dogs.DogId > d2.DogId
    );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン
    オプション4

    別のオプションは次のとおりです:

    DELETE FROM Dogs
    WHERE DogId > (
      SELECT MIN(DogId) FROM Dogs d2  
      WHERE Dogs.FirstName = d2.FirstName
      AND Dogs.LastName = d2.LastName
    );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン
    オプション5

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

    したがって、 rowidを使用できます DogIdの代わりにクエリで 列:

    DELETE FROM Dogs
    WHERE EXISTS (
      SELECT 1 FROM Dogs d2 
      WHERE Dogs.FirstName = d2.FirstName
      AND Dogs.LastName = d2.LastName
      AND Dogs.rowid > d2.rowid
    );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン

    この例は少し不必要に思えるかもしれませんが、すでに主キー列があることを考えると、 rowidを使用したい場合があります。 。 rowid 何らかの理由で主キー列を使用できない場合、またはテーブルに主キーがない場合に役立ちます。また、Oracleのドキュメントには、 rowidと記載されています。 値は、単一の行にアクセスするための最速の方法です。

    オプション6

    これが他の例ですが、 rowid 主キーの代わりに:

    DELETE FROM Dogs
    WHERE rowid > (
      SELECT MIN(rowid) FROM Dogs d2  
      WHERE Dogs.FirstName = d2.FirstName
      AND Dogs.LastName = d2.LastName
    );
    
    SELECT * FROM Dogs;

    結果:

    DOGID FIRSTNAME
    1 バーク スミス
    3 Woof ジョーンズ
    4 ラフ ロビンソン
    5 ワグ ジョンソン

    1. Javaでpl/sql関数を呼び出しますか?

    2. MySQLで特定の文字のASCIIコードを見つける方法

    3. MySQLTunerを使用してMySQLのパフォーマンスを最適化する方法

    4. 複数のアレイを並列にネスト解除します