Как удалить дубликаты в таблице 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    |                |
+---------------+-------------+------+-----+---------+----------------+
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 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);