Як видалити певний рядок із таблиці mysql з однаковими значеннями стовпців?


153

У мене проблема з запитами в MySQL. Моя таблиця має 4 стовпчики, і вона виглядає приблизно так:

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

id_usersі id_productє сторонніми ключами від різних таблиць.

Я хочу лише видалити один рядок:

1     2     1    2013

Що з’являється двічі, тому я просто хочу його видалити.

Я спробував цей запит:

delete from orders where id_users = 1 and id_product = 2

Але це видалить їх обох (оскільки вони дублюються). Будь-які натяки на вирішення цієї проблеми?

Відповіді:


208

Додайте запит limitна видалення

delete from orders 
where id_users = 1 and id_product = 2
limit 1

3
Це видаляє лише один рядок. Якщо з цим користувачем і ідентифікатором продукту було 3, то 2 залишилося б.
Роб

10
Так, ОП скажіть, що він хоче видалити 1 рядок. Ось що робить мій запит.
juergen d

2
Так, але я думаю, що це не те, чого він / вона хоче.
Роб

3
Дякую, Юрген. Це все, що мені потрібно!
Дані

3
Що дійсно потрібно зробити, це перевірити спочатку, які рядки дублюються, а потім видалити дублікати.
wbinky

64

Усі таблиці повинні мати первинний ключ (складається з одного або декількох стовпців), а дублюючі рядки не мають сенсу у реляційній базі даних. Ви можете обмежити кількість видалених рядків, використовуючи LIMIT:

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

Але це просто вирішує поточну проблему, ви обов'язково повинні працювати над більшою проблемою, визначаючи первинні ключі.


1
Це добре зазначити, що первинний ключ повинен бути унікальним у реляційній базі даних.
Павло

1
@Paul Це саме те, що я збираюся сказати. Але не забувайте, що унікальний ключ не потрібен, означає первинний ключ.
Райан Фунг

20

Вам потрібно вказати кількість рядків, які слід видалити. У вашому випадку (і я припускаю, що ви хочете зберегти лише один) це можна зробити так:

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)

Дякую, Роб, але ні ... Я просто хочу видалити один рядок, а не зберегти лише один
Dani

Це не працює для мене в 5.5.40, він видає синтаксичну помилку. Як згадувалося тут: stackoverflow.com/a/578926/1076075 , схоже, що ми не можемо використовувати підзапит для визначення значення пропозиції LIMIT. Для тих , хто намагається зробити речі таким чином, перевірити це: stackoverflow.com/q/578867/1076075
Bharadwaj Srigiriraju

8

Найкращий спосіб розробити таблицю - додати один тимчасовий рядок як автоматичне збільшення та зберегти як основний ключ. Тож ми можемо уникати таких вище питань.


1
Або постійний ряд. Я знаю, що це старе питання, але я хоч і повинен це сказати. Ідентифікатори використовуються для подібної ситуації. Якщо вас турбує простір: BIGINT - це лише 8 байт!
Ісмаель Мігель

5

Відповіді для видалення рядка вже є LIMIT. В ідеалі у вас повинен бути первинний ключ у вашому столі. Але якщо немає.

Я дам інші способи:

  1. Створюючи унікальний індекс

Я бачу, що id_users та id_product мають бути унікальними у вашому прикладі.

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

Вони видалять повторювані рядки з однаковими даними.

Але якщо ви все-таки отримаєте помилку, навіть якщо ви використовуєте пункт IGNORE, спробуйте це:

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. Створивши знову таблицю

Якщо є кілька рядків, які мають повторювані значення, то ви також можете відтворити таблицю

RENAME TABLE `orders` TO `orders2`;

CREATE TABLE `orders` 
SELECT * FROM `orders2` GROUP BY id_users, id_product;

1

Ви повинні додати ідентифікатор, який автоматично збільшується для кожного рядка, після чого ви можете видалити рядок за його ідентифікатором. тож ваша таблиця матиме унікальний ідентифікатор для кожного рядка та id_user, id_product ecc ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.