このテーブルの重複するレコードを削除する必要があります。ただし、各行に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
があった場合、次のように使用できます。
DELETE p1 FROM products p1
INNER JOIN products p2
WHERE p1.id < p2.id AND p1.product = p2.product;
レコードを一意に識別するフィールドの組み合わせはありません。
少なくとも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;
Akinasの回答とは別に、両方の行を削除してから1つ挿入できます。
また、パフォーマンスのために必要がない場合でも、特にこのような状況を回避するために、テーブルに主キーを本当に追加する必要があります。
あなたはできる
Delete <condition> limit 1
これにより、複数の行が条件に一致した場合でも、1行のみが削除されます。これは公式マニュアルで説明されています:
削除の順序
DELETEステートメントにORDER BY句が含まれている場合、行は句で指定された順序で削除されます。これは主にLIMITと組み合わせて使用すると便利です。たとえば、次のステートメントはWHERE句に一致する行を検索し、それらをtimestamp_columnでソートして、最初の(最も古い)行を削除します。
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;