J'ai une table de jeux, qui est décrite comme suit:
+---------------+-------------+------+-----+---------+----------------+
| 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 | |
+---------------+-------------+------+-----+---------+----------------+
Mais chaque jeu a une entrée en double dans le tableau quelque part, car chaque jeu était dans les horaires de deux équipes. Existe-t-il une instruction SQL que je peux utiliser pour parcourir et supprimer tous les doublons en fonction des champs identiques de date, heure, hometeam_id, awayteam_id, locationcity et locationstate?
Vous devez pouvoir effectuer une sous-requête corrélée pour supprimer les données. Recherchez toutes les lignes qui sont en double et supprimez toutes sauf celle avec le plus petit identifiant. Pour MYSQL, une jointure interne (équivalent fonctionnel d'EXISTS) doit être utilisée, comme ceci:
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)
Pour tester, remplacez delete games from games
avec select * from games
. Ne vous contentez pas d'exécuter une suppression sur votre base de données :-)
Vous pouvez essayer une telle requête:
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 )
Cela ne laissera dans la base de données qu'un exemple de chaque instance de jeu qui a le plus petit identifiant.
La meilleure chose qui a fonctionné pour moi a été de recréer la table.
CREATE TABLE newtable SELECT * FROM oldtable GROUP BY field1,field2;
Vous pouvez ensuite renommer.
Pour obtenir la liste des entrées en double correspondant à deux champs
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
Et pour supprimer tous les doublons uniquement
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
cela devrait vous donner les doublons; vous pouvez l'utiliser comme sous-requête pour spécifier les ID à supprimer.
delete from games
where id not in
(select max(id) from games
group by date, time, hometeam_id, awayteam_id, locationcity, locationstate
);
Workaround
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);
Tant que vous n'obtenez pas l'id (clé primaire) de la table dans votre requête de sélection et que les autres données sont exactement les mêmes, vous pouvez utiliser SELECT DISTINCT
pour éviter d'obtenir des résultats en double.
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
...))