数据源同步后删除重复条目的SQL查询实现方法
按业务字段去重保留最新导入记录的最优实现方案
核心前提:所有去重操作必须先做全量数据备份,禁止未备份直接执行硬删除,从流程上避免有效数据丢失
第一步:先统一时间字段的比较基准
你样例里的ImportDate是dd.MM.yy格式的字符串,直接用字符串排序会在跨月、跨年场景出现排序错误,必须先转成标准时间类型(datetime/时间戳),作为判断记录新旧的唯一依据,这步是所有后续逻辑正确的基础。
第二步:核心去重逻辑
不管你是在数据库层处理,还是拉取数据后用代码处理,核心逻辑完全一致:
- 以
a、b、c三个业务字段为分组维度做聚合 - 每个分组内按
ImportDate倒序排列,仅保留排在第一位的最新记录 - 其余记录判定为冗余数据,做删除/标记处理
常见场景的落地代码
场景1:数据存在MySQL/PostgreSQL等支持窗口函数的关系型数据库
直接在数据库层执行逻辑,不需要把全量数据拉到内存,效率最高,适合数据量较大的场景:
-- 第一步:先查询所有要保留的记录,人工核对结果是否符合预期 WITH ranked_data AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY a, b, c ORDER BY STR_TO_DATE(ImportDate, '%d.%m.%y') DESC -- 按你的实际时间格式调整解析规则 ) AS row_rank FROM your_raw_table ) SELECT * FROM ranked_data WHERE row_rank = 1;
确认查询返回的结果和预期一致(比如你给的3条样例数据会正确返回前2条),再执行删除操作:
-- 执行前确认已经完成全表备份 DELETE FROM your_raw_table WHERE id NOT IN ( SELECT id FROM ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( PARTITION BY a, b, c ORDER BY STR_TO_DATE(ImportDate, '%d.%m.%y') DESC ) AS row_rank FROM your_raw_table ) AS t WHERE row_rank = 1 ) AS t2 );
场景2:用Python等代码在拉取数据后做预处理再入库
适合每次拉取数据量不大的场景,参考实现:
import pandas as pd # df为合并了历史存量+当日拉取新数据的数据集 # 先把ImportDate转为可比较的时间类型 df['ImportDate'] = pd.to_datetime(df['ImportDate'], format='%d.%m.%y') # 按导入时间倒序后,按业务字段去重保留第一条(即最新的) df_dedup = df.sort_values('ImportDate', ascending=False).drop_duplicates(subset=['a','b','c'], keep='first')
第三步:强制校验流程(绝对不能省略,避免误删)
- 数量校验:去重后的总记录数,必须等于
按a、b、c三个字段分组的总组数,如果数量不匹配说明逻辑存在bug - 抽样校验:随机抽取10-20组存在重复的业务字段组合,手动核对保留的是否确实是ImportDate最新的记录
- 软删除过渡:给表加
is_valid字段,先把冗余数据标记为无效,不要直接硬删,观察2-3个拉取周期,确认业务侧没有数据异常后,再定期清理标记为无效的冗余数据,把误删风险降到0。
定时任务场景的优化建议
你是每24小时拉取一次数据,不需要每次都对全量数据做去重:每次拉到当日新数据后,只需要和历史表中同a、b、c的记录比ImportDate,如果当日数据更新就覆盖旧记录,否则直接跳过即可,处理数据量小,运行效率高,也能避免全量操作带来的批量误删风险。
内容的提问来源于stack exchange,提问作者kiooikml
相关产品推荐
相关产品推荐

