mysql查重处理问题

来源:互联网 发布:java stringbuffer数组 编辑:程序博客网 时间:2024/06/05 00:15

碰巧今天需要对数据库中某个字段进行查重,并对重复的记录进行操作,于是上网查找了关于mysql数据库查重的语句,查了很多,给出的结果都是
SELECT j1.id FROM jokes j1 WHERE j1.content IN (SELECT content FROM jokes GROUP BY content HAVING COUNT(content) > 1)

这里content是jokes表中的一个非主键字段。

然而坑人的事情就这样发生,这条语句运行起来,简直慢的令人发指,全程没有耐心等待,这都查询不出结果,跟不用说修改和删除操作了。下面是这个语句查询的用时结果:

SELECT j1.id FROM jokes j1 WHERE j1.content IN (SELECT content FROM jokes WHERE content !='' GROUP BY content HAVING COUNT(content) > 1)
执行:8 min 27 sec     总数:8 min 27 sec    630行

8分半,这是多久的时间啊,仅仅一条查询语句居然需要这么久的时间,可见效率是有多么的低。

于是我又想到了建立临时表的方法查询:

CREATE TABLE jokes_bak AS (SELECT content FROM jokes GROUP BY content HAVING COUNT(content) > 1)
建立临时表以后,进行查询:

SELECT id FROM jokes WHERE content IN (SELECT content FROM jokes_bak)
执行:0.252 sec     总数:0.253 sec    630行
这个结果总算感觉正常了,那么接下来皆可以进行一系列的修改删除操作了,如:

修改操作:update jokes set content = 'chongfu' where content in ( SELECT content FROM jokes_bak)

共 630 行受到影响
执行耗时   : 1.545 sec
传送时间   : 0 sec
总耗时      : 1.546 sec

删除操作类似,其中,删除多余重复,留下id最小一条记录的操作为:

DELETE FROM jokes WHERE content IN (SELECT content FROM jokes_bak) AND id NOT IN (SELECT MIN(id) FROM jokes WHERE content IN (SELECT content FROM jokes_bak) GROUP BY content)
通过搜索资料和尝试,发现还可以使用inner join来查询,查询结果如下:

SELECT j1.id FROM jokes j1INNER JOIN (SELECT content FROM jokes WHERE content !='' GROUP BY content HAVING COUNT(content) > 1) AS j2 USING(content)

执行:0.384 sec     总数:0.386 sec    630行

显然时间比第一种in的方式快的多,而事实上mysql中in、like应该尽量少用,第一种语句慢的另一个原因是因为没有建立索引。

那么这里还有另外一个问题,使用inner join的好处显而易见,不用额外建立一个临时表,但是进行修改删除操作的时候就出问题了,我使用一下语句进行修改:

UPDATE jokes SET SUBJECT = 'chongfu' WHERE id IN (SELECT j1.id FROM jokes j1INNER JOIN (SELECT content FROM jokes GROUP BY content HAVING COUNT(content) > 1) AS j2 USING(content))

提示错误:

错误代码: 1093

You can't specify target table 'jokes' for update in FROM clause

这个错误应该是mysql禁止对同一个表进行嵌套修改,防止一些错误的产生,这里解决这个问题的方法是,嵌套一层表查询,给表起个别名:

UPDATE jokes SET content='重复段子' WHERE id IN(SELECT jd.id FROM(SELECT j1.id FROM jokes j1INNER JOIN (SELECT content FROM jokes GROUP BY content HAVING COUNT(content) > 1) AS j2 USING(content)) jd)





0 0