J'ai besoin de supprimer les enregistrements en double dans ce tableau. Cependant, il n'y a pas de id
pour chaque ligne.
+---------+--------+----------+
| product | amount | quantity |
+---------+--------+----------+
| table | 2000 | 5 |
| chair | 300 | 25 |
| TV | 30000 | 4 |
| bike | 300 | 25 |
| table | 2000 | 5 |
| chair | 300 | 25 |
| chair | 300 | 25 |
+---------+--------+----------+
J'ai besoin d'obtenir ce résultat.
+---------+--------+----------+
| product | amount | quantity |
+---------+--------+----------+
| table | 2000 | 5 |
| chair | 300 | 25 |
| TV | 30000 | 4 |
| bike | 300 | 25 |
+---------+--------+----------+
S'il y avait un id
, j'aurais pu utiliser:
DELETE p1 FROM products p1
INNER JOIN products p2
WHERE p1.id < p2.id AND p1.product = p2.product;
Il n'y a aucune combinaison de champs qui identifie l'enregistrement de manière unique.
Je vois au moins 2 solutions différentes.
Première solution: déplacer des enregistrements uniques vers une copie de la table et remplacer la table d'origine.
CREATE TABLE temp LIKE products;
INSERT INTO temp
SELECT DISTINCT * FROM products;
DROP TABLE products;
RENAME TABLE temp TO products;
Deuxième solution: ajoutez l'auto-incrémentation temporaire, supprimez les enregistrements qui l'utilisent et supprimez le champ temporaire.
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;
MISE À JOUR
Dans la deuxième variante: la définition de colonne supplémentaire en tant que clé primaire est redondante. Il suffit d'utiliser
ALTER TABLE products ADD COLUMN temp SERIAL;
En dehors de la réponse d'Akinas, vous pouvez supprimer les deux lignes, puis en insérer une.
Vous devez également vraiment, vraiment ajouter une clé primaire à votre table même si vous n'en avez pas besoin pour les performances, en particulier pour éviter des situations comme celle-ci.
Vous pourriez faire un
Delete <condition> limit 1
Cela supprimera seulement 1 ligne, même si plusieurs lignes correspondent à la condition. Ceci est expliqué dans le manuel officiel:
Ordre de suppression
Si l'instruction DELETE inclut une clause ORDER BY, les lignes sont supprimées dans l'ordre spécifié par la clause. Ceci est utile principalement en conjonction avec LIMIT. Par exemple, l'instruction suivante recherche les lignes correspondant à la clause WHERE, les trie par timestamp_column et supprime la première (la plus ancienne):
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;