web-dev-qa-db-ja.com

一時テーブルなしでMySQLテーブルのすべての重複レコードを削除する方法

私はこれについて多くのバリエーションを見てきましたが、私が達成しようとしているものと完全に一致するものはありません。

テーブルTableAがあります。このテーブルには、構成可能なアンケートに対するユーザーの回答が含まれています。列はmember_id, quiz_num, question_num, answer_numです。

どういうわけか、数人のメンバーが回答を2回提出しました。そのため、重複したレコードを削除する必要がありますが、1行が残されていることを確認してください。

primary列はないため、まったく同じデータを持つ2行または3行が存在する可能性があります。

すべての重複を削除するクエリはありますか?

45
MivaScott

テーブルにnique Indexを追加します。

ALTER IGNORE TABLE `TableA`   
ADD UNIQUE INDEX (`member_id`, `quiz_num`, `question_num`, `answer_num`);

これを行う別の方法は次のとおりです。

テーブルに主キーを追加すると、次のクエリを使用してテーブルから重複を簡単に削除できます。

DELETE FROM member  
WHERE id IN (SELECT * 
             FROM (SELECT id FROM member 
                   GROUP BY member_id, quiz_num, question_num, answer_num HAVING (COUNT(*) > 1)
                  ) AS A
            );
101
Saharsh Shah

これはTEMPテーブルを使用せず、代わりに実際のテーブルを使用します。問題が一時テーブルに関するものであり、テーブルの作成または削除に関するものではない場合、これは機能します。

SELECT DISTINCT * INTO TableA_Verify FROM TableA;

DROP TABLE TableA;

RENAME TABLE TableA_Verify TO TableA;
13
christoph

drop table TableAの代わりに、すべてのレジスター(delete from TableA;)を削除してから、TableA_Verifyからのレジスター(insert into TAbleA select * from TAbleA_Verify)を元のテーブルに追加できます。この方法では、元のテーブル(インデックスなど)へのすべての参照が失われることはありません。

CREATE TABLE TableA_Verify AS SELECT DISTINCT * FROM TableA;

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;
13
jveirasv

上記の答えをくれたjveirasvに感謝します。

特定の列セットの重複を削除する必要がある場合は、これを使用できます(たとえば、テーブル内のタイムスタンプが異なる場合)

CREATE TABLE TableA_Verify AS SELECT * FROM TableA WHERE 1 GROUP BY [COLUMN TO remove duplicates BY];

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;
7
nikolais

テーブルに一意のインデックスを追加します。

ALTER IGNORE TABLE TableA   
ADD UNIQUE INDEX (member_id, quiz_num, question_num, answer_num);

とても上手です

6
Dina Elwy

主キーを使用していない場合は、1回のストロークで次のクエリを実行します。値を置き換えることにより:

# table_name - Your Table Name
# column_name_of_duplicates - Name of column where duplicate entries are found

create table table_name_temp like table_name;
insert into table_name_temp select distinct(column_name_of_duplicates),value,type from table_name group by column_name_of_duplicates;
delete from table_name;
insert into table_name select * from table_name_temp;
drop table table_name_temp
  1. 一時テーブルを作成し、個別の(重複しない)値を保存する
  2. 空の元のテーブルを作成する
  3. 一時テーブルから元のテーブルに値を挿入します
  4. 一時テーブルを削除する

データベースを使用する前に、データベースのバックアップを取ることを常にお勧めします。

3
Sandesh Mhatre

別の方法は、同じ構造を持つ新しい一時テーブルを作成することです。

CREATE TABLE temp_table AS SELECT * FROM original_table LIMIT 0

次に、テーブルに主キーを作成します。

ALTER TABLE temp_table ADD PRIMARY KEY (primary-key-field)

最後に、重複レコードを無視しながら、元のテーブルからすべてのレコードをコピーします。

INSERT IGNORE INTO temp_table AS SELECT * FROM original_table

これで、元のテーブルを削除して、新しいテーブルの名前を変更できます。

DROP TABLE original_table
RENAME TABLE temp_table TO original_table
1
user1838915

コメントに記載されているように、アイテムが複数回複製される場合、Saharsh Shahの回答のクエリを複数回実行する必要があります。

これは、データを削除せず、元のテーブルにデータを常に保持し、テーブルを「ライブ」に保ちながら重複を削除できるソリューションです。

alter table tableA add column duplicate tinyint(1) not null default '0';

update tableA set
duplicate=if(@member_id=member_id
             and @quiz_num=quiz_num
             and @question_num=question_num
             and @answer_num=answer_num,1,0),
member_id=(@member_id:=member_id),
quiz_num=(@quiz_num:=quiz_num),
question_num=(@question_num:=question_num),
answer_num=(@answer_num:=answer_num)
order by member_id, quiz_num, question_num, answer_num;

delete from tableA where duplicate=1;

alter table tableA drop column duplicate;

これは基本的に、現在の行が最後の行と同じかどうかを確認し、同じ場合は重複としてマークします(順序ステートメントにより、重複が確実に隣り合わせに表示されます)。次に、重複したレコードを削除します。最後のduplicate列を削除して、元の状態に戻します。

alter table ignoreもすぐになくなる可能性があります: http://dev.mysql.com/worklog/task/?id=7395

1
juacala