アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

重複レコードを削除

MySQLを前提として書いています


移転前の記事で書いてたクエリがめちゃくちゃ頭悪かったので完全に書き直し。

やりたいこと

テーブル `table` があるとする。
フィールドは `id`, `hoge` の2つで、`id` がプライマリキー。

`hoge`の値が一意でない場合、重複しないように余分なレコードを削除したい。
(残すのは`id`が最も小さいレコード)

id hoge
1 a
2 a
3 b
4 b

id hoge
1 a
3 b

方法

手順

①`table`を構造のみコピーする(`table_copy`とする)
②残したいレコードを`table_copy`にコピーする
③`table`を削除し、`table_copy`を`table`にリネーム

①`table`を構造のみコピーする

めんどくさいのでphpMyAdminでぽちぽちとコピーすればOK。

次にめんどくさくない手段としては以下クエリを打ってから`table`と同じインデックスを作るなどする。

CREATE TABLE `table_copy`
SELECT * FROM `table` LIMIT 0;

何かしらの事情できっちりやる必要がある人は自分でCREATE文書いてください。

CREATE TABLE `table_copy` (
  `id`   INT(11)    NOT NULL COMMENT 'ID',
  `hoge` VARCHAR(8) NOT NULL COMMENT 'ほげ',
  PRIMARY KEY (`id`) ,
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT = 'テーブル';

②残したいレコードを`table_copy`にコピーする

INSERT INTO `table_copy` (`id`, `hoge`)
SELECT   MIN(`id`) AS `id`, `hoge`
FROM     `table`
GROUP BY `hoge`;

③`table`を削除し、`table_copy`を`table`にリネーム

-- 削除
DROP TABLE `table`;

-- リネーム
RENAME TABLE `table_copy` TO `table` ;

何らかの理由で削除+リネームがよろしくない場合、
`table_copy`に存在しないレコードを`table`から削除、でもOK。

DELETE FROM `table`
LEFT JOIN   `table_copy` ON `table`.`id` = `table_copy`.`id`
WHERE       `table_copy`.`id` IS NOT NULL;