テーブル table_a
id | name | typeID |
---|---|---|
1 | 星宮いちご | 1 |
2 | 霧矢あおい | 2 |
3 | 紫吹蘭 | 3 |
4 | 大空あかり | 1 |
table_a
のtypeID
カラムのデータが重複してるレコードを削除しようとして次のようなSQLを発行しました。
DELETE FROM table_a WHERE typeID IN ( SELECT typeID FROM table_a GROUP BY typeID HAVING COUNT(*) >= 2 );
You can't specify target table 'table_a' for update in FROM clause
というエラーになってしまいました。
どうやら、DELETE, UPDATEでデータを操作するテーブルと同じ名前がサブクエリ内にあるとダメなようです。
このエラーは、テーブルを変更し、さらにサブクエリーで同じテーブルから選択しようとする次のような場合に発生します。
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);サブクエリーはSELECT
ステートメントだけでなく、UPDATE
およびDELETE
ステートメント内でも正当であるため、UPDATE
ステートメント内の割り当てのためにサブクエリーを使用できます。ただし、サブクエリーのFROM
句と更新のターゲットの両方に同じテーブル (この場合は、テーブルt1
) を使用することはできません。
出典: [https://dev.mysql.com/doc/refman/5.6/ja/subquery-errors.html:title]
サブクエリで取得してる部分を更にサブクエリにしてASで別名にして取得するようにすればOK
ニホンゴで書くと判りにくいけど、要はこんな感じ
DELETE FROM table_a WHERE typeID IN ( SELECT typeID FROM ( SELECT typeID FROM table_a GROUP BY typeID HAVING COUNT(*) >= 2 ) AS tmp );
サブクエリで取得しているtypeID
カラムのデータが重複している部分が、DELETE する際のクエリではtmp
扱いになって、同じテーブルの名が重複しなくなるということっぽい。
ただ上記のクエリでは、実際に削除するために選択しているレコードはこんな感じになります。
mysql > SELECT * FROM table_a WHERE typeID IN ( SELECT typeID FROM table_a GROUP BY typeID HAVING COUNT(typeID) >= 2 ); +----+-----------------+--------+ | id | name | typeID | +----+-----------------+--------+ | 1 | 星宮いちご | 1 | | 4 | 大空あかり | 1 | +----+-----------------+--------+
なので実際に削除を実行すると…
mysql > DELETE FROM table_a WHERE typeID IN ( SELECT typeID FROM ( SELECT typeID FROM table_a GROUP BY typeID HAVING COUNT(*) >= 2 ) AS tmp ); Query OK, 2 rows affected (0.10 sec) mysql > SELECT * FROM table_a; +----+-----------------+--------+ | id | name | typeID | +----+-----------------+--------+ | 2 | 霧矢あおい | 2 | | 3 | 紫吹蘭 | 3 | +----+-----------------+--------+
typeID
が重複しているデータを全て削除してしまいます。
一部のカラムが重複したデータを1件だけ残して削除するには工夫が必要そうです。
(つづく...
[参考]
- 作者: 加嵜長門,田宮直人,丸山弘詩
- 出版社/メーカー: マイナビ出版
- 発売日: 2017/03/27
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る