データベース - SQL 基本構文 - 重複データを削除する
1. 概要 こんなバカなことになったのは、わたしくらいのものかと思っていたら、検索したら、例題が載っていたので、こんなことになることも少なからずあるのだとわかりました。 わたしのケースは、何度かデータベースを移植しているうちにこうなっちゃったようです。 そもそも、テーブルにプライマリキーを作成していなかったっけ? と驚くばかりなのですが。 同じ値を持つレコードが4つずつ存在しているのです。 2. Oracle の場合 Oracle ではどうやるか・・・。 「重複レコードの削除方法 - オラクル・Oracleをマスターするための基本と仕組み」にありました。 残すレコードを抽出するやり方は、何やら難しそうですが。 そもそも同じデータなのでどれかが残れば構わないというやり方が DELETE FROM テーブル T1 WHERE ROWID > ( SELECT MIN(ROWID) FROM テーブル T2 WHERE T1.カラム1 = T2.カラム1 AND T1.カラム2 = T2.カラム2 ); これは簡単。 Oracle の場合、ROWID なるものが存在するのね。 3. MySQL の場合 MySQL の例は「[SQL]重複データを1件だけ残して削除する方法」にありました。 DELETE FROM テーブル WHERE ID NOT IN ( SELECT TMP1.ID FROM ( SELECT MIN(ID) AS ID FROM テーブル GROUP BY TMP1.カラム1, TMP1.カラム2 ) AS TMP1 ); だそうで。 MySQL には「ID」ってのが存在するのか、カラム名なのかちょっと不明ですが、調べる元気がないので次に進みます。 4. postgreSQL の場合 postgreSQL の例は「重複したレコードを1件だけ残して削除したい」にありました。 いくつか方法が提示されていましたが。 とても一般的とは思えませんが、postgreSQL の 9.1 以降だと WITH というのを使ってできるそうで WITH TMP AS(DELETE FROM テーブル RETURNING *) INSERT INTO テーブル SELECT DISTINCT * FROM TMP; 何やら呪文のようですが。 用心のためバックアップをとっておいて実行してみました。 結果は・・・満足のいくものが得られました。 重複がなくなった時点でプライマリキーを設定しました。
DELETE FROM テーブル T1 WHERE ROWID > ( SELECT MIN(ROWID) FROM テーブル T2 WHERE T1.カラム1 = T2.カラム1 AND T1.カラム2 = T2.カラム2 );
DELETE FROM テーブル WHERE ID NOT IN ( SELECT TMP1.ID FROM ( SELECT MIN(ID) AS ID FROM テーブル GROUP BY TMP1.カラム1, TMP1.カラム2 ) AS TMP1 );
WITH TMP AS(DELETE FROM テーブル RETURNING *) INSERT INTO テーブル SELECT DISTINCT * FROM TMP;