MySQL удаление дубликатов данных - PullRequest
4 голосов
/ 27 января 2010

Здесь отображаются все имена и фамилии, которые имеют ровно две одинаковые записи.

SELECT `firstname`,`lastname`,COUNT(*) AS Count 
FROM `people` 
GROUP BY `firstname`,`lastname`
HAVING Count = 2

Как мне превратить это в оператор DELETE FROM WHERE с LIMIT, чтобы удалить только одну из каждой записи и оставить другую.

хорошо, похоже, это технический способ, я просто собираюсь сделать это в цикле php while

Ответы [ 3 ]

2 голосов
/ 27 января 2010

Вы можете создать таблицу с 1 записью каждого из дубликатов: затем удалить все записи дублирования из таблицы сотрудников и затем повторно вставить записи дублирования.

-- Setup for example
create table people (fname varchar(10), lname varchar(10));

insert into people values ('Bob', 'Newhart');
insert into people values ('Bob', 'Newhart');
insert into people values ('Bill', 'Cosby');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Adam', 'Sandler');

-- Show table with duplicates
select * from people;

-- Create table with one version of each duplicate record
create table dups as 
    select distinct fname, lname, count(*) 
    from people group by fname, lname 
    having count(*) > 1;

-- Delete all matching duplicate records
delete people from people inner join dups 
on people.fname = dups.fname AND 
   people.lname = dups.lname;

-- Insert single record of each dup back into table
insert into people select fname, lname from dups;

-- Show Fixed table
select * from people;
1 голос
/ 27 января 2010

если у вас есть первичный ключ, такой как id, вы можете сделать:

delete from people 
where id not in
(
      select minid from 
      (select min(id) as minid from people 
      group by firstname, lastname) as newtable
)

Бит подзапроса select min(id)... получает уникальные (на основе идентификатора) строки для заданной комбинации имени, фамилии; а затем вы удаляете все остальные строки, т.е. ваши дубликаты. Вам нужно обернуть свой подзапрос из-за ошибки в MySQL, в противном случае мы могли бы сделать:

delete from people 
where id not in
(
      select min(id) as minid from people 
      group by firstname, lastname
)

лучше было бы:

delete people from 
people left outer join
(
  select min(id) as minid from people 
  group by firstname, lastname
) people_grouped
on people.first_name = people_grouped.first_name
and people.last_name = people_grouped.last_name
and people_grouped.id is null

чтобы избежать подзапроса.

0 голосов
/ 27 января 2010

Создайте новую таблицу и добавьте уникальный ключ (имя, фамилия). Затем вставьте строки в старой таблице в новую таблицу. Затем переименуйте таблицы.

mysql> select * from t;
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| A         | B        | 
| A         | B        | 
| X         | Y        | 
+-----------+----------+
3 rows in set (0.00 sec)

mysql> create table t2 like t;
Query OK, 0 rows affected (0.00 sec)

mysql> alter table t2 add unique key name(firstname,lastname);
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert ignore into t2 select * from t;
Query OK, 2 rows affected (0.00 sec)
Records: 3  Duplicates: 1  Warnings: 0


mysql> select * from t2;
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| A         | B        | 
| X         | Y        | 
+-----------+----------+
2 rows in set (0.01 sec)
...