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

テーブル内の重複の各セットの1行を除くすべてを選択および/または削除するにはどうすればよいですか?

    これが1つの解決策です。これをMySQL5.5.8でテストしました。

    SELECT MAX(COALESCE(c2.id, c1.id)) AS id,
     c1.driver_id, c1.car_id,
     c2.notes AS notes
    FROM cars_drivers AS c1
    LEFT OUTER JOIN cars_drivers AS c2
     ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c2.notes IS NOT NULL
    GROUP BY c1.driver_id, c1.car_id, c2.notes;
    

    driver_id、car_idの値ごとにnull以外のメモを含む複数の行がある可能性があるため、c2.notesをGROUPBYキーとして含めます。

    サンプルデータを使用した結果:

    +------+-----------+--------+-------+
    | id   | driver_id | car_id | notes |
    +------+-----------+--------+-------+
    |    2 |         1 |      1 | NULL  |
    |    4 |         2 |      1 | NULL  |
    |    8 |         3 |      2 | hi    |
    |    9 |         5 |      3 | NULL  |
    +------+-----------+--------+-------+
    

    削除について。サンプルデータでは、保持するのは常にdriver_idおよびcar_idごとの最大のid値です。これに依存できる場合は、複数テーブルの削除を実行して、id値が高く、同じdriver_idとcar_idを持つ行が存在するすべての行を削除できます。

    DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
     ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c1.id < c2.id;
    

    これにより、内部結合の条件でID値が異なる2つの行が必要になるため、driver_idとcar_idの値の特定のペアで1つの行のみが存在する場合は当然スキップされます。

    ただし、グループごとの最新のIDが保持したいものであることに依存できない場合、ソリューションはより複雑になります。 1つのステートメントで解決するよりもおそらく複雑なので、2つのステートメントで解決してください。

    テスト用にさらに2行追加した後、これもテストしました:

    INSERT INTO cars_drivers VALUES (10,2,3,NULL), (11,2,3,'bye');
    
    +----+--------+-----------+-------+
    | id | car_id | driver_id | notes |
    +----+--------+-----------+-------+
    |  1 |      1 |         1 | NULL  |
    |  2 |      1 |         1 | NULL  |
    |  3 |      1 |         2 | NULL  |
    |  4 |      1 |         2 | NULL  |
    |  5 |      2 |         3 | NULL  |
    |  6 |      2 |         3 | NULL  |
    |  7 |      2 |         3 | NULL  |
    |  8 |      2 |         3 | hi    |
    |  9 |      3 |         5 | NULL  |
    | 10 |      2 |         3 | NULL  |
    | 11 |      2 |         3 | bye   |
    +----+--------+-----------+-------+
    

    最初に、null以外のメモが含まれる行が存在する場合に、nullメモが含まれる行を削除します。

    DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
     ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id)
    WHERE c1.notes IS NULL AND c2.notes IS NOT NULL;
    
    +----+--------+-----------+-------+
    | id | car_id | driver_id | notes |
    +----+--------+-----------+-------+
    |  1 |      1 |         1 | NULL  |
    |  2 |      1 |         1 | NULL  |
    |  3 |      1 |         2 | NULL  |
    |  4 |      1 |         2 | NULL  |
    |  8 |      2 |         3 | hi    |
    |  9 |      3 |         5 | NULL  |
    | 11 |      2 |         3 | bye   |
    +----+--------+-----------+-------+
    

    次に、重複の各グループから最も高いIDの行を除くすべてを削除します。

    DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
     ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c1.id < c2.id;
    
    +----+--------+-----------+-------+
    | id | car_id | driver_id | notes |
    +----+--------+-----------+-------+
    |  2 |      1 |         1 | NULL  |
    |  4 |      1 |         2 | NULL  |
    |  9 |      3 |         5 | NULL  |
    | 11 |      2 |         3 | bye   |
    +----+--------+-----------+-------+
    


    1. バルクSMSの送信は途中で停止します

    2. varcharまたはintの主キーを使用してテーブルを設計する必要がありますか?

    3. SQL Server(T-SQL)ですべての言語のリストを取得する方法

    4. mysqlのselectでif/else条件を使用する方法