基于非匹配列值跨表插入数据时出现重复问题排查
以下是几种常见的错误根源,结合你的场景逐一排查:
NOT EXISTS判断逻辑用错了字段
核心需求是判断「业务上的新数据」,但如果你的NOT EXISTS仅用每日变化的LoadDate做对比,会导致Staging表所有当日数据都被判定为“新数据”全量插入,直接造成重复。
必须用业务唯一标识字段(比如用户ID、订单编号这类不会随LoadDate变化的字段)来做判断,而非依赖LoadDate。
错误写法示例:INSERT INTO Final (Col1, Col2, LoadDate) SELECT Col1, Col2, LoadDate FROM Staging s WHERE NOT EXISTS ( SELECT 1 FROM Final f WHERE f.LoadDate = s.LoadDate -- 仅用LoadDate判断,完全不符合需求 )正确写法示例(假设Col1+Col2是业务唯一键):
INSERT INTO Final (Col1, Col2, LoadDate) SELECT Col1, Col2, LoadDate FROM Staging s WHERE NOT EXISTS ( SELECT 1 FROM Final f WHERE f.Col1 = s.Col1 AND f.Col2 = s.Col2 -- 覆盖所有业务唯一字段 )Staging表本身存在重复数据
即使NOT EXISTS逻辑正确,如果每日刷新的Staging表未做去重处理,源数据本身包含多条相同业务键的记录,第一次插入时这些重复数据会全部被写入Final表,直接造成重复。因此Staging表刷新时必须先对业务唯一键做去重。Final表未设置唯一约束
就算NOT EXISTS逻辑没问题,如果Final表没有给业务唯一键设置主键或唯一约束,会出现两种问题:一是之前某次逻辑错误插入的重复数据无法被阻止;二是高并发场景下,多个会话同时执行插入时会出现竞态条件——每个会话的NOT EXISTS都判断数据不存在,最终导致重复插入。LoadDate的精度或格式不一致
如果LoadDate是带时分秒的datetime类型,判断时未做日期截断,或者Staging和Final表的LoadDate字段类型不一致(比如一个是datetime,一个是date),可能会导致同一业务数据被误判为“新数据”重复插入。比如Staging的LoadDate是2024-05-20 14:30:00,Final里的是2024-05-20 09:15:00,错误用LoadDate判断会认为是不同记录。
内容的提问来源于stack exchange,提问作者Dhiraj D

