web-dev-qa-db-ja.com

複数のフィールドに基づいて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    |                |
+---------------+-------------+------+-----+---------+----------------+

しかし、各ゲームは2つのチームのスケジュールに含まれていたため、テーブルのどこかに重複したエントリがあります。同一の日付、時刻、hometeam_id、awayteam_id、locationcity、locationstateフィールドに基づいてすべての重複を調べて削除するために使用できるSQL文はありますか?

24
cfrederich

相関サブクエリを実行してデータを削除できるはずです。重複するすべての行を検索し、IDが最小の行を除くすべてを削除します。 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 with select * from games。 DBで削除を実行しないでください:-)

45
N West

このようなクエリを試すことができます:

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 )

これにより、最小のIDを持つ各ゲームインスタンスの1つの例のみがデータベースに残ります。

13

私のために働いた最高のことは、テーブルを再作成することでした。

CREATE TABLE newtable SELECT * FROM oldtable GROUP BY field1,field2;

その後、名前を変更できます。

7
Ali Hashemi

2つのフィールドと一致する重複エントリのリストを取得するには

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;
5
Rem
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を指定できます。

4
Neville Kuyt
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);
2
piotrpo

選択クエリでテーブルのID(主キー)を取得しておらず、他のデータが完全に同じである限り、SELECT DISTINCTを使用して重複する結果を取得しないようにすることができます。

2
Wicked Coder
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
                          ...))
1
limscoder