web-dev-qa-db-ja.com

MySQLのOne以外のすべての重複行を削除しますか?

可能な重複:
MySQLの重複行を削除する

MySQLテーブルからすべての重複データを削除する方法

たとえば、次のようになります。

SELECT * FROM names;

+----+--------+
| id | name   |
+----+--------+
| 1  | google |
| 2  | yahoo  |
| 3  | msn    |
| 4  | google |
| 5  | google |
| 6  | yahoo  |
+----+--------+

SELECTクエリであれば、SELECT DISTINCT name FROM names;を使用します。

重複を削除してそれぞれ1つのレコードだけを保持するために、これをDELETEでどのようにしたらよいでしょうか。

394
Highway of Life

編集者警告:この解決策は計算上非効率的で大きなテーブルへの接続を断念するかもしれません。

NB - あなたのテーブルのテストコピーに対して最初にこれを実行するには、必要を使用してください。

実行したとき、AND n1.id <> n2.idも含めない限り、テーブルのすべての行が削除されることがわかりました。

  1. 行を最小のid値で保持したい場合は、次のようにします。

    DELETE n1 FROM names n1, names n2 WHERE n1.id > n2.id AND n1.name = n2.name
    
  2. 行を最も高いid値で保持したい場合は、次のようにします。

    DELETE n1 FROM names n1, names n2 WHERE n1.id < n2.id AND n1.name = n2.name
    

私はMySQL 5.1でこの方法を使いました

他のバージョンについてはわかりません。


更新:重複を削除するためにグーグルを使っている人はここで終わる
OPの質問はDELETEに関するものですが、INSERTDISTINCTを使う方がはるかに速いことに注意してください。 800万行のデータベースの場合、以下のクエリは13分かかりましたが、DELETEを使用した場合、2時間以上かかりましたが、完了しませんでした。

INSERT INTO tempTableName(cellId,attributeId,entityRowId,value)
    SELECT DISTINCT cellId,attributeId,entityRowId,value
    FROM tableName;
889
martin.masa

行を最小のid値で保持したい場合は、次のようにします。

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MIN(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

最も高いid値が必要な場合は、次のようにします。

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MAX(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

サブクエリ内のサブクエリはMySQLに必要です、さもないと1093エラーが発生します。

181
OMG Ponies