web-dev-qa-db-ja.com

IDのないテーブルで、MySQLの重複レコードを削除する方法は?

このテーブルの重複するレコードを削除する必要があります。ただし、各行にidはありません。

データの例

+---------+--------+----------+
| product | amount | quantity |
+---------+--------+----------+
| table   |   2000 |        5 |
| chair   |    300 |       25 |
| TV      |  30000 |        4 |
| bike    |    300 |       25 |
| table   |   2000 |        5 |
| chair   |    300 |       25 |
| chair   |    300 |       25 |
+---------+--------+----------+

予期された結果

この結果を取得する必要があります。

+---------+--------+----------+
| product | amount | quantity |
+---------+--------+----------+
| table   |   2000 |        5 |
| chair   |    300 |       25 |
| TV      |  30000 |        4 |
| bike    |    300 |       25 |
+---------+--------+----------+

ID付きスクリプト

idがあった場合、次のように使用できます。

DELETE p1 FROM products p1
INNER JOIN products p2 
WHERE p1.id < p2.id AND p1.product = p2.product;
1
Edwin Babu

レコードを一意に識別するフィールドの組み合わせはありません。

少なくとも2つの異なるソリューションが表示されます。

最初の解決策:一意のレコードをテーブルのコピーに移動し、元のテーブルを置き換えます。

CREATE TABLE temp LIKE products;
INSERT INTO temp 
    SELECT DISTINCT * FROM products;
DROP TABLE products;
RENAME TABLE temp TO products;

2番目の解決策:一時的な自動インクリメントを追加し、それを使用してレコードを削除し、一時フィールドをドロップします。

ALTER TABLE products ADD COLUMN temp SERIAL PRIMARY KEY;
DELETE t1.* 
    FROM products t1 
    LEFT JOIN ( SELECT MIN(temp) mintemp 
                FROM products
                GROUP BY field1,field2 /* , ... */ , fieldN) t2 
        ON t1.temp=t2.mintemp 
    WHERE t2.mintemp IS NULL;
ALTER TABLE products DROP COLUMN temp;


[〜#〜]更新[〜#〜]

2番目のバリアント:主キーとしての追加の列定義は冗長です。使うのに十分です

ALTER TABLE products ADD COLUMN temp SERIAL;
13
Akina

Akinasの回答とは別に、両方の行を削除してから1つ挿入できます。

また、パフォーマンスのために必要がない場合でも、特にこのような状況を回避するために、テーブルに主キーを本当に追加する必要があります。

3
Guran

あなたはできる

Delete <condition> limit 1

これにより、複数の行が条件に一致した場合でも、1行のみが削除されます。これは公式マニュアルで説明されています:

削除の順序

DELETEステートメントにORDER BY句が含まれている場合、行は句で指定された順序で削除されます。これは主にLIMITと組み合わせて使用​​すると便利です。たとえば、次のステートメントはWHERE句に一致する行を検索し、それらをtimestamp_columnでソートして、最初の(最も古い)行を削除します。

DELETE FROM somelog WHERE user = 'jcole'
ORDER BY timestamp_column LIMIT 1;
0
MTilsted