Jak usunąć określony wiersz z tabeli mysql z tymi samymi wartościami kolumn?

153

Mam problem z zapytaniami w MySQL. Moja tabela ma 4 kolumny i wygląda mniej więcej tak:

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

id_usersi id_productsą kluczami obcymi z różnych tabel.

Chcę usunąć tylko jeden wiersz:

1     2     1    2013

Który pojawia się dwukrotnie, więc chcę go tylko usunąć.

Próbowałem tego zapytania:

delete from orders where id_users = 1 and id_product = 2

Ale usunie oba z nich (ponieważ są zduplikowane). Jakieś wskazówki dotyczące rozwiązania tego problemu?

Dani
źródło

Odpowiedzi:

208

Dodaj limitdo zapytania usuwającego

delete from orders 
where id_users = 1 and id_product = 2
limit 1
juergen d
źródło
3
Spowoduje to usunięcie tylko jednego wiersza. Gdyby były 3 z tym użytkownikiem i identyfikatorem produktu, 2 pozostałyby.
Rob
10
Tak, OP mówi, że chce usunąć 1 wiersz. Tak właśnie działa moje zapytanie.
juergen d
2
Tak, ale myślę, że nie tego chce.
Rob
3
Dziękuję Juergen. To wszystko, czego potrzebuję!
Dani
3
To, co naprawdę musi zrobić OP, to najpierw sprawdzić, które wiersze są zduplikowane, a następnie usunąć duplikaty.
wbinky,
64

Wszystkie tabele powinny mieć klucz podstawowy (składający się z jednej lub wielu kolumn), zduplikowane wiersze nie mają sensu w relacyjnej bazie danych. Możesz ograniczyć liczbę usuwanych wierszy za pomocą LIMIT:

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

Ale to tylko rozwiązuje twój obecny problem, zdecydowanie powinieneś popracować nad większym problemem, definiując klucze podstawowe.

dnet
źródło
1
Warto wspomnieć, że klucz podstawowy powinien być unikalny w relacyjnej bazie danych.
Paul,
1
@Paul To jest dokładnie to, co mam zamiar powiedzieć. Ale nie zapominaj, że unikalny klucz nie oznacza klucza podstawowego.
Ryan Fung
20

Musisz określić liczbę wierszy, które mają zostać usunięte. W twoim przypadku (i zakładam, że chcesz zachować tylko jeden) można to zrobić w następujący sposób:

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)
Obrabować
źródło
Dziękuję Rob, ale nie ... Chcę tylko usunąć jeden wiersz, a nie tylko jeden
Dani
To nie działa dla mnie w 5.5.40, generuje błąd składni. Jak wspomniano tutaj: stackoverflow.com/a/578926/1076075 , wygląda na to, że nie możemy użyć podzapytania do określenia wartości klauzuli LIMIT. Dla każdego, kto próbuje zrobić coś w ten sposób, sprawdź to: stackoverflow.com/q/578867/1076075
Bharadwaj Srigiraju
8

Najlepszym sposobem zaprojektowania tabeli jest dodanie jednego tymczasowego wiersza jako automatycznego zwiększania i zachowanie jako klucza podstawowego. Dzięki temu możemy uniknąć takich powyższych problemów.

praveenraj4ever
źródło
1
Lub stały rząd. Wiem, że to stare pytanie, ale pomyślałem, że powinienem je powiedzieć. Id są używane w tego rodzaju sytuacjach. Jeśli martwisz się o miejsce: BIGINT to tylko 8 bajtów!
Ismael Miguel
5

Istnieją już odpowiedzi dotyczące usuwania wiersza według LIMIT. Idealnie powinieneś mieć klucz podstawowy w swojej tabeli. Ale jeśli nie ma.

Podam inne sposoby:

  1. Tworząc Unique index

Widzę, że id_users i id_product powinny być unikalne w twoim przykładzie.

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

Spowoduje to usunięcie zduplikowanych wierszy z tymi samymi danymi.

Ale jeśli nadal otrzymujesz błąd, nawet jeśli używasz klauzuli IGNORE, spróbuj tego:

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. Tworząc ponownie tabelę

Jeśli istnieje wiele wierszy, które mają zduplikowane wartości, możesz również ponownie utworzyć tabelę

RENAME TABLE `orders` TO `orders2`;

CREATE TABLE `orders` 
SELECT * FROM `orders2` GROUP BY id_users, id_product;
Somnath Muluk
źródło
1

Musisz dodać identyfikator, który jest automatycznie zwiększany dla każdego wiersza, po czym możesz usunąć wiersz według jego identyfikatora. więc twoja tabela będzie miała unikalny identyfikator dla każdego wiersza i id_user, id_product ecc ...

Andrei Tornea
źródło