如何去除数据表中的重复数据
通常情况下,一个我们在做一个产品的时候,一开始可能由于设计考虑不周或者程序写的不够严谨,某个字段上的值产生重复了,但是又必须去掉,这个时候就稍微麻烦了一点,直接加一个 UNIQUE KEY
肯定是不行了,因为会报错。
现在,我们来采用一种变通的办法,不过可能会丢失一些数据 :)
在这里,我们设定一个表,其结构如下:
mysql> desc `user`; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(10) | NO | | | | | extra | char(10) | NO | | | | +-------+------------------+------+-----+---------+----------------+
原来表中的数据假定有以下几条:
mysql> SELECT * FROM `user`; +----+-------+--------+ | id | name | extra | +----+-------+--------+ | 1 | user1 | user1 | | 2 | user2 | user2 | | 3 | user3 | user3 | | 4 | user4 | user4 | | 5 | user5 | user5 | | 6 | user3 | user6 | | 7 | user6 | user7 | | 8 | user2 | user8 | | 9 | USER2 | user9 | | 10 | USER6 | user10 | +----+-------+--------+
1、将原来的数据导出
mysql>SELECT * INTO OUTFILE '/tmp/user.txt' FROM `user`;
2、清空数据表
mysql>TRUNCATE TABLE `user`;
3、创建唯一索引,并且修改 `name` 字段的类型为 BINARY CHAR
区分大小写
mysql> ALTER TABLE `user` MODIFY `name` CHAR(10) BINARY NOT NULL DEFAULT ''; mysql> ALTER TABLE `user` ADD UNIQUE KEY ( `name` );
现在来看看新的表结构:
mysql> desc user; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(10) | NO | UNI | | | | extra | char(10) | NO | | | | +-------+------------------+------+-----+---------+----------------+
4、把数据导回去,在这里,有两种选择:新的重复记录替换旧的记录,只保留最新的记录
或者是 新的记录略过,只保留最旧的记录
mysql> LOAD DATA INFILE '/tmp/user.txt' REPLACE INTO TABLE `user`; Query OK, 10 rows affected (0.00 sec) Records: 8 Deleted: 2 Skipped: 0 Warnings: 0 mysql> SELECT * FROM USER; +----+-------+--------+ | id | name | extra | +----+-------+--------+ | 1 | user1 | user1 | | 8 | user2 | user8 | | 6 | user3 | user6 | | 4 | user4 | user4 | | 5 | user5 | user5 | | 7 | user6 | user7 | | 9 | USER2 | user9 | | 10 | USER6 | user10 | +----+-------+--------+
上面是采用 REPLACE
的方式,可以看到,导入过程中删掉了两条数据,结果验证确实是 新的重复记录替换旧的记录,只保留最新的记录
。
现在,来看看用 IGNORE
的方式:
mysql> LOAD DATA INFILE '/tmp/user.txt' IGNORE INTO TABLE `user`; Query OK, 6 rows affected (0.01 sec) Records: 8 Deleted: 0 Skipped: 2 Warnings: 0 mysql> SELECT * FROM USER; +----+-------+--------+ | id | name | extra | +----+-------+--------+ | 1 | user1 | user1 | | 2 | user2 | user2 | | 3 | user3 | user3 | | 4 | user4 | user4 | | 5 | user5 | user5 | | 7 | user6 | user7 | | 9 | USER2 | user9 | | 10 | USER6 | user10 | +----+-------+--------+
看到了吧,确实是 新的记录略过,只保留最旧的记录
。
评论
lazcat_wu (未验证)
周三, 2007/01/17 - 09:49
Permalink
看了大大的说明,有
看了大大的说明,有一点不是太明白?就是最后的IGNORE 的方式的结果,既然name字段已经是区分大小写了,why最后的2个字段:
| 8 | user2 | user8 |
| 9 | USER2 | user9 |
怎么会只有一个字段呢?
假设覆盖的话:新的记录略过,只保留最旧的记录。那么也应该是9略过,保留8的记录,怎么会出现8略过,9保留呢?希望大大解释一下,谢谢!
yejr
周三, 2007/01/17 - 11:02
Permalink
不是很明白你的意思
不是很明白你的意思,既然已经区分大小写了,那么 "user2" 和 "USER2" 就表示是两个不同的记录了。
MySQL中文网: http://imysql.cn
Google MySQL中文用户群:http://groups.google.com/group/imysql
给你的祝福,要让你招架不住!
游客 (未验证)
周日, 2011/04/03 - 10:49
Permalink
建立一个临时数组,用m
建立一个临时数组,用mysql_fetch_assoc 读取数据, 把避免重复的那个字段的值设置成 数组的 索引,就可以避免重复,然后truncate 表,然后insert
tystok
周二, 2007/01/23 - 16:01
Permalink
没有看到发表评论,所
没有看到发表评论,所以发到网站的论坛了.看到,补上.算是补过吧.
如何去除数据表中的重复数据利用数据导入导出的方式.这种方式是能实现的,数据建立唯一索引的.但有一个更为简单的方法,能达到这个目的.那就是 IGNORG,比如:
ALTER IGNORE TABLE `tbl_name` ADD UNIQUE (`un_name`);
tal_name 为表名,un_name唯一索引名.
IGNORE 是当出现错误时,也就是当前处理的记录,与前面处理过的数据的有冲突(重复),忽略之.使SQL继续进行,这样便把可以达到去重的目的.
引申:这个选项在insert中也存在.我们如果在一个执行过程中,有多个insert 时,不免会在唯一索引字段上会有重复的.那么,使用ignore 会使得insert继续进行.而不是中断.
yejr
周二, 2007/01/23 - 20:40
Permalink
是的,也可以这么做
是的,也可以这么做,不过不支持
REPLACE
模式。MySQL中文网: http://imysql.cn
Google MySQL中文用户群:http://groups.google.com/group/imysql
给你的祝福,要让你招架不住!
游客 (未验证)
周四, 2007/05/10 - 10:22
Permalink
想去除重复还不简单
想去除重复还不简单,将所有自段都设为主键,导入后再删除没用的键就行了。