Удаление повторяющихся строк в MySQL, пошаговое руководство
Создайте таблицу и вставьте несколько строк:
dev-db> create table penguins(foo int, bar varchar(15), baz datetime);
Query OK, 0 rows affected (0.07 sec)
dev-db> insert into penguins values(1, 'skipper', now());
dev-db> insert into penguins values(1, 'skipper', now());
dev-db> insert into penguins values(3, 'kowalski', now());
dev-db> insert into penguins values(3, 'kowalski', now());
dev-db> insert into penguins values(3, 'kowalski', now());
dev-db> insert into penguins values(4, 'rico', now());
Query OK, 6 rows affected (0.07 sec)
dev-db> select * from penguins;
+------+----------+---------------------+
| foo | bar | baz |
+------+----------+---------------------+
| 1 | skipper | 2014-08-25 14:21:54 |
| 1 | skipper | 2014-08-25 14:21:59 |
| 3 | kowalski | 2014-08-25 14:22:09 |
| 3 | kowalski | 2014-08-25 14:22:13 |
| 3 | kowalski | 2014-08-25 14:22:15 |
| 4 | rico | 2014-08-25 14:22:22 |
+------+----------+---------------------+
6 rows in set (0.00 sec)
Затем удалите дубликаты:
dev-db> delete a
-> from penguins a
-> left join(
-> select max(baz) maxtimestamp, foo, bar
-> from penguins
-> group by foo, bar) b
-> on a.baz = maxtimestamp and
-> a.foo = b.foo and
-> a.bar = b.bar
-> where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
Результат:
dev-db> select * from penguins;
+------+----------+---------------------+
| foo | bar | baz |
+------+----------+---------------------+
| 1 | skipper | 2014-08-25 14:21:59 |
| 3 | kowalski | 2014-08-25 14:22:15 |
| 4 | rico | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)
Что делает этот оператор удаления
Псевдокод: сгруппируйте строки по двум столбцам, для которых вы хотите удалить дубликаты. Выберите одну строку каждой группы для сохранения, используя максимальный агрегат. Левое объединение возвращает все строки из левой таблицы с соответствующими строками в правой таблице. В этом случае левая таблица содержит все строки в таблице, а правая содержит только те строки, которые имеют значение NULL (не одну строку на группу, которую вы хотите сохранить). Удаляя эти строки, у вас остается только один уникальный на группу.
Более подробное техническое объяснение, как читать этот оператор удаления sql:
Настольные пингвины с псевдонимом «a» оставлены соединенными с подмножеством настольных пингвинов, которое называется «b». Правая таблица «b», которая является подмножеством, находит максимальную временную метку, сгруппированную по foo и bar. Это соответствует левой таблице «а». (foo, bar, baz) слева имеет каждую строку в таблице. Правое подмножество 'b' имеет (maxtimestamp, foo, bar), которое соответствует левому только тому, которое является максимальным.
Каждая строка, отличная от max, имеет значение maxtimestamp, равное NULL. Отфильтруйте эти строки со значением NULL, и вы получите набор всех строк, сгруппированных по foo и bar, который не является последней базой меток времени. Удалить те.
Перед запуском сделайте резервную копию таблицы.
Предотвратите повторение этой проблемы в этой таблице:
Если вы заставили это сработать, и оно потушило ваш огонь "двойных рядов". Отлично. Ваша работа еще не закончена. Определите новый составной уникальный ключ в вашей таблице (в этих двух столбцах), чтобы предотвратить добавление дополнительных дубликатов. Подобно хорошей иммунной системе, плохие строки даже не должны попадать в таблицу во время вставки. Позже все эти программы, добавляющие дубликаты, будут транслировать свои протесты, и когда вы исправите их, эта проблема больше не возникнет.