oracle 去重并按时间排序取第一条

select  t.*  
   from (select a.*, row_number() over(partition by 需要分组的字段 order by 更新时间 desc) rw  
           from 表 a) t  
  where t.rw = 1  

row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。 

与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪劣rownum然后再进行排序,而此函数在包含排序从句后是先排序再计算行号码。 

row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开始排序)。 

rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内) 

dense_rank()也是连续排序,有两个第二名时仍然跟着第三名。相比之下row_number是没有重复值的。 

oracle 分析函数 row_number(),返回一个整数值(>=1);

 

例子1:

有个需求是营销客户活动表中activityId和cifNo是唯一索引,但是表中索引创建错误,导致表中存在很多activityId和cifNo重复的记录,而且两条重复记录中有一条的VISIT_TIMES是大于1的,我们现在要做的是,删除这个营销客户活动表中重复的记录,删除VISIT_TIMES等于0的那条,怎么做?

--根据activity_id、cif_no分组,分组内根据visit_times倒序,找出所有记录
select *, row_number() over(PARTITION by ACTIVITY_ID, CIF_NO order by VISIT_TIMES DESC) RN from MKT_ACTIVITY_CIF_5

--找出按activityId、cif_no分组后,重复的记录
select * from (
 select *, row_number() over(PARTITION by ACTIVITY_ID, CIF_NO order by VISIT_TIMES DESC) RN from MKT_ACTIVITY_CIF_5
) t WHERE t.RN > 1

select ACTIVITY_CIF_ID from (
 select *, row_number() over(PARTITION by ACTIVITY_ID, CIF_NO order by VISIT_TIMES DESC) RN from MKT_ACTIVITY_CIF_5
) t WHERE t.RN > 1

--根据ACTIVITY_CIF_ID删除重复的记录
delete from MKT_ACTIVITY_CIF_5 where ACTIVITY_CIF_ID in (
select ACTIVITY_CIF_ID from (
 select *, row_number() over(PARTITION by ACTIVITY_ID, CIF_NO order by VISIT_TIMES DESC) RN from MKT_ACTIVITY_CIF_5
) t WHERE t.RN > 1

删除完成后验证是否还有重复记录,期望:无记录

select activity_id, cif_no from MKT_ACTIVITY_CIF_5 group by ACTIVITY_ID , CIF_NO HAVING count(*) > 1

 

posted on 2017-09-29 00:48  有点懒惰的大青年  阅读(2693)  评论(0)    收藏  举报