Comment supprimer une certaine ligne de la table mysql avec les mêmes valeurs de colonne?

153

J'ai un problème avec mes requêtes dans MySQL. Mon tableau a 4 colonnes et il ressemble à ceci:

id_users    id_product    quantity    date
 1              2              1       2013
 1              2              1       2013
 2              2              1       2013
 1              3              1       2013

id_userset id_productsont des clés étrangères de différentes tables.

Ce que je veux, c'est supprimer une seule ligne:

1     2     1    2013

Ce qui apparaît deux fois, donc je veux juste le supprimer.

J'ai essayé cette requête:

delete from orders where id_users = 1 and id_product = 2

Mais il supprimera les deux (car ils sont dupliqués). Des conseils pour résoudre ce problème?

Dani
la source

Réponses:

208

Ajouter un limità la requête de suppression

delete from orders 
where id_users = 1 and id_product = 2
limit 1
juergen d
la source
3
Cela ne supprime qu'une seule ligne. S'il y en avait 3 avec cet utilisateur et cet identifiant de produit, il en resterait 2.
Rob
10
Oui, OP dit qu'il souhaite supprimer 1 ligne. C'est ce que fait ma requête.
juergen d
2
Oui, mais je pense que ce n'est pas ce qu'il / elle veut.
Rob
3
Merci Juergen. C'est tout ce dont j'ai besoin!
Dani
3
Ce que OP doit vraiment faire est de vérifier d'abord quelles lignes sont dupliquées, puis de supprimer les doublons.
wbinky
64

Toutes les tables doivent avoir une clé primaire (constituée d'une ou de plusieurs colonnes), les lignes en double n'ont pas de sens dans une base de données relationnelle. Vous pouvez limiter le nombre de lignes de suppression en utilisant LIMITcependant:

DELETE FROM orders WHERE id_users = 1 AND id_product = 2 LIMIT 1

Mais cela ne résout que votre problème actuel, vous devriez certainement travailler sur le plus gros problème en définissant des clés primaires.

dnet
la source
1
Il est bon de mentionner que la clé primaire doit être unique dans une base de données relationnelle.
Paul
1
@Paul C'est exactement ce que je vais dire. Mais n'oubliez pas que la clé unique ne signifie pas nécessairement la clé primaire.
Ryan Fung
20

Vous devez spécifier le nombre de lignes à supprimer. Dans votre cas (et je suppose que vous ne voulez en garder qu'un), cela peut être fait comme ceci:

DELETE FROM your_table WHERE id_users=1 AND id_product=2
LIMIT (SELECT COUNT(*)-1 FROM your_table WHERE id_users=1 AND id_product=2)
Rob
la source
Merci Rob, mais non ... Je veux juste supprimer une seule ligne, pas pour en garder une seule
Dani
Cela ne fonctionne pas pour moi dans la version 5.5.40, cela génère une erreur de syntaxe. Comme mentionné ici: stackoverflow.com/a/578926/1076075 , il semble que nous ne puissions pas utiliser une sous-requête pour spécifier la valeur d'une clause LIMIT. Pour tous ceux qui essaient de faire les choses de cette façon, consultez ceci: stackoverflow.com/q/578867/1076075
Bharadwaj Srigiriraju
8

La meilleure façon de concevoir une table est d'ajouter une ligne temporaire comme incrémentation automatique et de la conserver comme clé primaire. Nous pouvons donc éviter les problèmes ci-dessus.

praveenraj4ever
la source
1
Ou une ligne permanente. Je sais que c'est une vieille question, mais je pensais que je devrais le dire. Les identifiants sont utilisés pour ce genre de situation. Si vous êtes préoccupé par l'espace: un BIGINT ne fait que 8 octets!
Ismael Miguel
5

Il existe déjà des réponses pour Supprimer une ligne par LIMIT. Idéalement, vous devriez avoir une clé primaire dans votre table. Mais s'il n'y en a pas.

Je vais donner d'autres moyens:

  1. En créant un index unique

Je vois que id_users et id_product devraient être uniques dans votre exemple.

ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)

Cela supprimera les lignes en double avec les mêmes données.

Mais si vous obtenez toujours une erreur, même si vous utilisez la clause IGNORE, essayez ceci:

ALTER TABLE orders ENGINE MyISAM;
ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)
ALTER TABLE orders ENGINE InnoDB; 
  1. En créant à nouveau la table

S'il y a plusieurs lignes qui ont des valeurs en double, vous pouvez également recréer la table

RENAME TABLE `orders` TO `orders2`;

CREATE TABLE `orders` 
SELECT * FROM `orders2` GROUP BY id_users, id_product;
Somnath Muluk
la source
1

Vous devez ajouter un identifiant qui s'incrémente automatiquement pour chaque ligne, après quoi vous pouvez supprimer la ligne par son identifiant. donc votre table aura un identifiant unique pour chaque ligne et le id_user, id_product ecc ...

Andrei Tornea
la source