Удаление повторяющихся записей в таблице соединений - PullRequest
4 голосов
/ 14 февраля 2011

У меня есть связь HABTM между пользователем и ролью.

Пользователь может быть администратором (role_id = 1) или пользователем (role_id = 2) для ролей.

В таблице соединений, role_users, у меня есть несколько избыточных записей. Например:

enter image description here

Я хочу удалить дубликаты записей, такие как 1: 1, 2: 4.

Два вопроса:

  1. Где лучше всего выполнить скрипт sql, который удаляет дублирование - миграция? скрипт?

  2. Что такое SQL-запрос для удаления дубликатов?

Ответы [ 2 ]

12 голосов
/ 14 февраля 2011
CREATE TABLE roles_users2 LIKE roles_users; -- this ensures indexes are preserved
INSERT INTO roles_users2 SELECT DISTINCT * FROM roles_users; 
DROP TABLE roles_users;
RENAME TABLE roles_users2 TO roles_users;

и на будущее, чтобы предотвратить дублирование строк

ALTER TABLE roles_users ADD UNIQUE INDEX (role_id, user_id);

Или вы можете сделать все это за один шаг с помощью ALTER TABLE IGNORE:

ALTER IGNORE TABLE roles_users ADD UNIQUE INDEX (role_id, user_id);

IGNORE - это расширение MySQL для стандартного SQL.Он управляет работой ALTER TABLE, если в новой таблице присутствуют дубликаты уникальных ключей или появляются предупреждения при включенном строгом режиме.Если IGNORE не указан, копия прерывается и откатывается при возникновении ошибок дубликата ключа.Если указан IGNORE, используется только первая строка из строк с дубликатами на уникальном ключе.Другие конфликтующие строки удаляются.Неверные значения усекаются до ближайшего подходящего допустимого значения.

3 голосов
/ 14 февраля 2011

Самое простое - скопировать данные в новую таблицу, за исключением дубликатов:

CREATE TABLE roles_users2 AS
SELECT DISTINCT * FROM roles_users

Затем вы можете выбрать один из следующих вариантов:

  • Удалите старую таблицу, переименуйте новую таблицу в старое имя и добавьте индексы.
  • Обрезать старую таблицу и вставить строки из role_users2 обратно в role_users.
...