之前线上遇到了个问题,需要临时处理一下同步过来的数据,删除重复项,当时没写出来这个sql,泪目.....
正好空下来了,理一下怎么写这个sql
sql主要用到的还是 row_number这个函数,他会为根据指定条件,每行数据分配一个序号
语法格式:row_number() over(partition by 分组列 order by 排序列 desc)
先把表结构列一下:
uuid varchar2(32) primary key
userid varchar2(32)
work-date date
value number
因对接方数据存在问题,导致出现 相同的userid, work-date, value 有两条相同的数据,现在需要删除重复的数据
筛选sql写法:
SELECT * FROM (
SELECT uuid, row_number() over(partition BY USERID, work-date, value order by UUID) rn, USERID, work-date, value
FROM table.data
) t WHERE t.rn >1;
简单解释,先通过 USERID, work-date, value 分组,查出来 每条数据的row_number
在通过row_number 筛选出 序号大于1 的,则能查询出所有重复的数据
最后按照 查出来的 uuid 删除就可以实现去重了
如果表设计的时候,没有uuid这种唯一标识字段,可以先查出来所有重复数据,再删除所有重复的数据,最后把数据插入进去,这样也能实现去重的效果
这个 主要用的oracle 函数还是 row_number这个函数,记录一下,以免下次用的时候想不起来~
说句题外话,在表设计的时候,需要考虑一下排查问题可能用到的字段,比如这次的表虽然把数据存下来了,但是没有对方传的username,我们通过 username 去映射到指定的userid,这样如果数据出了问题,也不清楚是哪条数据
此外,同步时间也可以加上,单看表数据,也不知道是什么时间点写入的,线上的业务在实时用这张表的数据,数据存在问题可以通过同步时间字段,快速判断是否最新的数据
第二点,对面提供的是个分页接口,实际上这么写是有问题的,场景是我们每四个小时会调用他们的接口获取所有的数据,先删后增数据
如果在接口调用期间,数据分页的位置出现变动,则同样会导致同步过来的数据重复的问题