- MySQL
- 2021-08-26 - 更新:2024-06-05
MySQLのテーブルで指定した列のデータが重複しているレコードを抽出、及び削除する方法をご紹介します。
まずはサンプルのテーブルを用意しましょう。
CREATE TABLE `sample` ( `id` int(8) NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `type` int(4) NOT NULL, PRIMARY KEY (`id`) );
サンプルデータを登録します。
INSERT INTO `sample` VALUES (DEFAULT, '赤井', 1), (DEFAULT, '井田', 2), (DEFAULT, '宇野', 3), (DEFAULT, '江崎', 1), (DEFAULT, '奥本', 2);
テーブルの中身を見てみると次のようになります。
mysql> select * from `sample`; +----+--------+------+ | id | name | type | +----+--------+------+ | 1 | 赤井 | 1 | | 2 | 井田 | 2 | | 3 | 宇野 | 3 | | 4 | 江崎 | 1 | | 5 | 奥本 | 2 | +----+--------+------+
typeに重複したデータがあることが分かります。
それではCOUNT関数とHAVING句を使って重複している件数を確認してみましょう。
mysql> SELECT type, count(*) as cnt FROM `sample` group by type having cnt > 1;
結果は次のようになります。
+------+-----+ | type | cnt | +------+-----+ | 1 | 2 | | 2 | 2 | +------+-----+
typeが「1」と「2」のデータが2件ずつあることが分かります。
重複データを抽出
まずは重複したデータを抽出してみましょう。
typeが同じでnameが違うデータを抽出します。
SELECT * FROM sample WHERE EXISTS ( SELECT * FROM sample isample WHERE sample.type = isample.type AND sample.name <> isample.name ) ORDER BY type, id ;
結果は次のようになります。
+----+--------+------+ | id | name | type | +----+--------+------+ | 1 | 赤井 | 1 | | 4 | 江崎 | 1 | | 2 | 井田 | 2 | | 5 | 奥本 | 2 | +----+--------+------+
データ量が多い場合等、上記クエリでは重くて表示できないときは次のように試してください。
SELECT * FROM sample GROUP BY type HAVING COUNT(type) > 1 AND COUNT(DISTINCT name) > 1;
結果には重複が省かれたデータが出力されますが、どのデータが対象かどうかは判断できます。
+----+--------+------+ | id | name | type | +----+--------+------+ | 1 | 赤井 | 1 | | 2 | 井田 | 2 | +----+--------+------+
重複データを削除
今度は重複したデータを削除してみましょう。
サブクエリーを利用して重複したデータを削除する
DELETE FROM `sample` WHERE id IN ( SELECT id FROM ( SELECT id FROM `sample` GROUP BY type HAVING COUNT(*) > 1 ) AS tmp );
上記のSQLを実行した後のテーブルの中身を見てみましょう。
mysql> select * from `sample`; +----+--------+------+ | id | name | type | +----+--------+------+ | 3 | 宇野 | 3 | | 4 | 江崎 | 1 | | 5 | 奥本 | 2 | +----+--------+------+
重複したデータが削除されていますね。
削除されるのはidが若い方のデータであることが分かります。
テーブルのデータを整理したいとき等に便利なので、是非使ってみてください。
おまけ
SQLにはDISTINCTという重複した行を排除することが出来る便利なコマンドがあります。
単純に一意なデータが欲しいとか、重複を省いた件数が知りたいなどといった場合に便利です。
重複するデータを省いたデータを表示する。
mysql> SELECT DISTINCT type FROM `sample`; +------+ | type | +------+ | 1 | | 2 | | 3 | +------+
重複するデータを省いたデータの件数を表示する。
SELECT COUNT(DISTINCT type) result FROM `sample`; +--------+ | result | +--------+ | 3 | +--------+
フィールドは複数指定することも可能です。
SELECT COUNT(DISTINCT name, type) result FROM `sample`;