这其实是一个面试题,但是我没答上来。(≧﹏ ≦)
一、需求
有一张表,数据类似于:
id name
1 x
2 x
3 y
4 z
5 z
要求删除name重复的记录,只留下同名的第一条
二、解决
1. 先创建表、测试数据
CREATE TABLE `test` ( `id` int(10) NOT NULL DEFAULT '0', `name` varchar(60) DEFAULT NULL, PRIMARY KEY (`id`) );insert into test values(1, 'zhangsan'), (2, 'zhangsan'), (3, 'lisi'), (4, 'wangwu'), (5, 'wangwu'), (6, 'wangwu'), (7, 'zhaoliu'), (8, 'zhaoliu'), (9, 'jack'), (10, 'rose');
数据如下
mysql> select * from test; +----+----------+ | id | name | +----+----------+ | 1 | zhangsan | | 2 | zhangsan | | 3 | lisi | | 4 | wangwu | | 5 | wangwu | | 6 | wangwu | | 7 | zhaoliu | | 8 | zhaoliu | | 9 | jack | | 10 | rose | +----+----------+ 10 rows in set (0.00 sec)
2. SQL
方法1:多表delete语法
mysql> DELETE ta FROM test ta,test tb where ta.name=tb.name and ta.id>tb.id; Query OK, 4 rows affected (0.05 sec)mysql> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
| 3 | lisi |
| 4 | wangwu |
| 7 | zhaoliu |
| 9 | jack |
| 10 | rose |
+----+----------+
6 rows in set (0.00 sec)
方法2:中间表的方式
create table test_tmp like test;insert into test_tmp select min(id), name from test group by name;
drop table test;
rename table test_tmp to test;
方法n
其实还有其他的方法,比如说:
- 新建test_tmp,在name字段上添加唯一索引,然后,用insert ignore into方法。
- 导出到文件,然后在加载回来的过程中去重。参考:imysql.cn/node/222
暂时不知道几种方法在性能上的优缺点。
3. 什么方法不行
mysql> delete from test where id not in (select min(id) as id from test group by name);
ERROR 1093 (HY000): You can't specify target table 'test' for update in FROM clause
不支持此语法!虽然这是我第一个想到的方法,我的MySQL是5.6.23版本的
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于