吃相难看的mysql重复数据删除

需求描述

数据库为mysql , 清理数据要对重复历史数据做删除操作, 环境有以下特点
- 目标表没有主键
- 不允许做表结构变动
- 重复数据并非全部字段重复, 只是部分标志字段重复

解决思路与困境解决

最初的思路是按照指定字段找出重复记录集, 每组仅保留一条记录, 其余数据做删除处理
伪sql实现如下:

delete from r_data_1d a 
where (a.c_res_id,a.c_task_time) in (select c_res_id,c_task_time from r_data_1d group by c_res_id,c_task_time having count(*) > 1) 
and a.rowid not in (select min(rowid) from r_data_1d group by c_res_id,c_task_time having count(*)>1) 

困境及解决方案:
1. mysql不支持rowid, 且表中没有主键.
解决方案: 采取 收集-删除-增补 三步走方式进行处理, 此处引进临时表 r_data_1d_temp
2. 处理删除步骤时, 发现mysql不支持对目标表进行删除中查询操作, 如该语句
delete from a where a.b in (select b from a group by b having count(*) > 1)

解决方案: 采取 收集-删除 两步完成该步骤, 此处引进临时表 r_data_1d_del_temp

最终方案

最终对上述步骤进行了整合, 简单描述为 收集补全-收集删除信息-执行删除-执行补全
最终sql如下:

create r_data_1d_temp
select c_business_id, c_res_id , c_sub_res_id , max(c_in_avg), max(c_in_min), max(c_in_max), max(c_out_avg), max(c_out_min), max(c_out_max), c_task_time , c_tag1, c_tag2 from (
select * from r_data_1d a where (a.c_res_id,a.c_task_time) in (select c_res_id,c_task_time from r_data_1d group by c_res_id,c_task_time having count(*) > 1) )a 
group by c_business_id, c_res_id, c_sub_res_id, c_task_time, c_tag1, c_tag2;

create table r_data_1d_del_temp select c_res_id,c_task_time from r_data_1d group by c_res_id,c_task_time having count(*) > 1;

delete from r_data_1d
where (c_res_id,c_task_time) in (select * from r_data_1d_del_temp);

drop table r_data_1d_del_temp;

insert into r_data_1d select * from r_data_1d_temp;

drop table r_data_1d_temp;

后记

目前该实现还是较为难看, 贴出来只是抛砖引玉, 希望能请到大神给出更优的解

猜你喜欢

转载自blog.csdn.net/bkk854762363/article/details/78438090