mysql之重复记录查询及去重

0. 前言

在实际的数据库设计过程中,很少通过索引组合键唯一索引来保证数据唯一性。很多是通过代码逻辑(先查询再插入)去保证唯一性,这个在并发很少的情况下是没有问题的,一般用在配置类的数据库表。不过在一些并发高的场景下,就会出现多线程问题,因为先查询再插入并非原子操作,另外当程序出错情况也会导致在数据库里存在重复记录。这个时候程序员就会被叫来背锅,首要的当然是处理掉已产生的重复数据保证业务正常运行,再排查问题原因。本文主要以mysql为例记录如何处理重复记录。

1. 查找重复记录
select * from 表 where 重复字段 in (select 重复字段 from 表 group by 
重复字段 having count(*)>1)

一个重复字段,以商家表中的qq重复字段处理为例:

select * from owner where qq in (select qq from owner group by qq
 having count(*) > 1)

多个重复字段,以商品的sku表中商品id、商品sku_code两个重复字段处理为例:

select * from sku where (product_id,sku_code) in (select product_id ,
 sku_code from sku group by product_id, sku_code having count(*) > 1)
2. 删除重复记录

网上很多版本:

delete from 表 where id not in (select min(id) from 表 group by 重复字段 having 
count(*)>1) and 重复字段 in (select 重复字段 from 表 group by 重复字段 having 
count(*)>1)

但是按这种处理,会发现在mysql中会报错“You can’t specify target table ‘pms_sku’ for update in FROM clause”意思就是“不能在同一个sql语句中,先select同一个表的某些值,然后再update这个表”
正常的做法应该是:

delete from  表 where id in (select id from (select  * from 表 where id not in (select min(id) from 表 group by 重复字段 having count(*)>1) and 重复字段 in (select 重复字段 from 表 group by 重复字段 having count(*)>1)
) 临时表)

也就是多嵌套一层select出来一个临时表
这里同样以删除sku 中以商品id、商品sku_code两个重复字段处理为例:

delete from sku WHERE id in(select id from (select * FROM sku WHERE 
(product_id,sku_code) IN (SELECT product_id,sku_code FROM sku GROUP BY 
product_id,sku_code HAVING COUNT(*)>1) and id not in (select min(id) from sku 
group by product_id,sku_code having count(*)>1)) a)
3. 最后

处理重复记录的方法,你学会了吗?当然如果业务明确,这些键是唯一的标识,可以建立唯一索引从数据库层面保证数据的唯一性。

上一篇:java 如何获取京东商品实时价格


下一篇:Java与ES