Как удалить повторяющиеся записи из БД MySQL?
У меня есть таблица с некоторыми идентификаторами + титулы. Я хочу сделать столбец заголовка уникальным, но у него уже есть более 600k записей, некоторые из которых являются дубликатами (иногда несколько десятков раз).
Как удалить все дубликаты, кроме одного, чтобы после этого добавить уникальный ключ в столбец заголовка?
8 ответов
эта команда добавляет уникальный ключ, и удаляет все строки, которые генерируют ошибки (из-за уникального ключа). Это удаляет дубликаты.
ALTER IGNORE TABLE table ADD UNIQUE KEY idx1(title);
Edit: обратите внимание, что эта команда может не работать для таблиц InnoDB для некоторых версий MySQL. См.этот пост для решения проблемы. (Спасибо "анонимному пользователю" за эту информацию.)
создайте новую таблицу только с отдельными строками исходной таблицы. Могут быть и другие способы, но я нахожу это самым чистым.
CREATE TABLE tmp_table AS SELECT DISTINCT [....] FROM main_table
более конкретно:
Более быстрый способ-вставить отдельные строки во временную таблицу. Используя delete, мне потребовалось несколько часов, чтобы удалить дубликаты из таблицы из 8 миллионов строк. Использование insert и distinct заняло всего 13 минут.
CREATE TABLE tempTableName LIKE tableName;
CREATE INDEX ix_all_id ON tableName(cellId,attributeId,entityRowId,value);
INSERT INTO tempTableName(cellId,attributeId,entityRowId,value) SELECT DISTINCT cellId,attributeId,entityRowId,value FROM tableName;
DROP TABLE tableName;
INSERT tableName SELECT * FROM tempTableName;
DROP TABLE tempTableName;
Это показывает, как это сделать в SQL2000. Я не совсем знаком с синтаксисом MySQL, но я уверен, что есть что-то сопоставимое
create table #titles (iid int identity (1, 1), title varchar(200))
-- Repeat this step many times to create duplicates
insert into #titles(title) values ('bob')
insert into #titles(title) values ('bob1')
insert into #titles(title) values ('bob2')
insert into #titles(title) values ('bob3')
insert into #titles(title) values ('bob4')
DELETE T FROM
#titles T left join
(
select title, min(iid) as minid from #titles group by title
) D on T.title = D.title and T.iid = D.minid
WHERE D.minid is null
Select * FROM #titles
delete from student where id in (
SELECT distinct(s1.`student_id`) from student as s1 inner join student as s2
where s1.`sex` = s2.`sex` and
s1.`student_id` > s2.`student_id` and
s1.`sex` = 'M'
ORDER BY `s1`.`student_id` ASC
)
решение, опубликованное Нитином, кажется самым элегантным / логичным.
однако у него есть одна проблема:
ошибка 1093 (HY000): вы не можете указать целевую таблицу "студент" для обновить предложение FROM
это, однако, может быть разрешено с помощью (SELECT * FROM student) вместо student:
DELETE FROM student WHERE id IN (
SELECT distinct(s1.`student_id`) FROM (SELECT * FROM student) AS s1 INNER JOIN (SELECT * FROM student) AS s2
WHERE s1.`sex` = s2.`sex` AND
s1.`student_id` > s2.`student_id` AND
s1.`sex` = 'M'
ORDER BY `s1`.`student_id` ASC
)
дать ваши +1 Нитин придумали оригинальное решение.
С MySql ALTER IGNORE TABLE
был осужден, вам нужно фактически удалить дубликат даты перед добавлением индекса.
сначала написать запрос, который находит все дубликаты. Здесь я предполагаю, что email
- это поле, содержащее дубликаты.
SELECT
s1.email
s1.id,
s1.created
s2.id,
s2.created
FROM
student AS s1
INNER JOIN
student AS s2
WHERE
/* Emails are the same */
s1.email = s2.email AND
/* DON'T select both accounts,
only select the one created later.
The serial id could also be used here */
s2.created > s1.created
;
Далее выберите только уникальные дубликаты идентификаторов:
SELECT
DISTINCT s2.id
FROM
student AS s1
INNER JOIN
student AS s2
WHERE
s1.email = s2.email AND
s2.created > s1.created
;
как только вы убедитесь, что содержит только дубликаты идентификаторов, которые вы хотите удалить, запустите delete. Вы должны добавить (SELECT * FROM tblname)
так что MySql не жалуется.
DELETE FROM
student
WHERE
id
IN (
SELECT
DISTINCT s2.id
FROM
(SELECT * FROM student) AS s1
INNER JOIN
(SELECT * FROM student) AS s2
WHERE
s1.email = s2.email AND
s2.created > s1.created
);
затем создайте уникальный индекс:
ALTER TABLE
student
ADD UNIQUE INDEX
idx_student_unique_email(email)
;
ниже запрос может быть использован для удаления всех дубликатов, кроме одной строки с наименьшим значением поля "id"
DELETE t1 FROM table_name t1, table_name t2 WHERE t1.id > t2.id AND t1.name = t2.name
аналогичным образом мы можем сохранить строку с самым высоким значением в " id " следующим образом
DELETE t1 FROM table_name t1, table_name t2 WHERE t1.id < t2.id AND t1.name = t2.name
удаление дубликатов в таблицах MySQL является общей проблемой, которая обычно поставляется с конкретными потребностями. В случае, если кто-то заинтересован, здесь (удалить повторяющиеся строки в MySQL) Я объясняю, как использовать временную таблицу для удаления дубликатов MySQL надежным и быстрым способом (с примерами для разных случаев использования).
в этом случае, что-то вроде этого должно работать:
-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;
-- add a unique constraint
ALTER TABLE tmp_table1 ADD UNIQUE(id, title);
-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;
-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;