Как удалить дубликаты в таблице SQL на основе нескольких полей
У меня есть таблица игр, который описывается следующим образом:
+---------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | date | NO | | NULL | |
| time | time | NO | | NULL | |
| hometeam_id | int(11) | NO | MUL | NULL | |
| awayteam_id | int(11) | NO | MUL | NULL | |
| locationcity | varchar(30) | NO | | NULL | |
| locationstate | varchar(20) | NO | | NULL | |
+---------------+-------------+------+-----+---------+----------------+
но каждая игра имеет дубликат записи в таблице где-то, потому что каждая игра была в расписании для двух команд. Есть ли инструкция sql, которую я могу использовать для просмотра и удаления всех дубликатов на основе идентичных полей date, time, hometeam_id, awayteam_id, locationcity и locationstate?
8 ответов
вы должны иметь возможность сделать коррелированный подзапрос для удаления данных. Найдите все повторяющиеся строки и удалите все, кроме строки с наименьшим идентификатором. Для MYSQL необходимо использовать внутреннее соединение (функциональный эквивалент EXISTS), например:
delete games from games inner join
(select min(id) minid, date, time,
hometeam_id, awayteam_id, locationcity, locationstate
from games
group by date, time, hometeam_id,
awayteam_id, locationcity, locationstate
having count(1) > 1) as duplicates
on (duplicates.date = games.date
and duplicates.time = games.time
and duplicates.hometeam_id = games.hometeam_id
and duplicates.awayteam_id = games.awayteam_id
and duplicates.locationcity = games.locationcity
and duplicates.locationstate = games.locationstate
and duplicates.minid <> games.id)
чтобы проверить, заменить delete games from games
С select * from games
. Не просто запустите delete в своей БД: -)
вы можете попробовать такой запрос:
DELETE FROM table_name AS t1
WHERE EXISTS (
SELECT 1 FROM table_name AS t2
WHERE t2.date = t1.date
AND t2.time = t1.time
AND t2.hometeam_id = t1.hometeam_id
AND t2.awayteam_id = t1.awayteam_id
AND t2.locationcity = t1.locationcity
AND t2.id > t1.id )
это оставит в базе данных только один пример каждого экземпляра игры,который имеет наименьший идентификатор.
лучшее, что сработало для меня, - это воссоздать таблицу.
CREATE TABLE newtable SELECT * FROM oldtable GROUP BY field1,field2;
вы можете переименовать.
чтобы получить список дубликатов, соответствующих двум полям
select t.ID, t.field1, t.field2
from (
select field1, field2
from table_name
group by field1, field2
having count(*) > 1) x, table_name t
where x.field1 = t.field1 and x.field2 = t.field2
order by t.field1, t.field2
и удалить все дубликаты только
DELETE x
FROM table_name x
JOIN table_name y
ON y.field1= x.field1
AND y.field2 = x.field2
AND y.id < x.id;
select orig.id,
dupl.id
from games orig,
games dupl
where orig.date = dupl.date
and orig.time = dupl.time
and orig.hometeam_id = dupl.hometeam_id
and orig. awayteam_id = dupl.awayeam_id
and orig.locationcity = dupl.locationcity
and orig.locationstate = dupl.locationstate
and orig.id < dupl.id
это должно дать вам дубликаты; вы можете использовать его в качестве подзапроса для указания идентификаторов для удаления.
пока вы не получаете id (первичный ключ) таблицы в запросе select, а другие данные точно такие же, как вы можете использовать SELECT DISTINCT
чтобы избежать дублирования результатов.
delete from games
where id not in
(select max(id) from games
group by date, time, hometeam_id, awayteam_id, locationcity, locationstate
);
решение
select max(id) id from games
group by date, time, hometeam_id, awayteam_id, locationcity, locationstate
into table temp_table;
delete from games where id in (select id from temp);
DELETE FROM table
WHERE id =
(SELECT t.id
FROM table as t
JOIN (table as tj ON (t.date = tj.data
AND t.hometeam_id = tj.hometeam_id
AND t.awayteam_id = tj.awayteam_id
...))