很早之前就涉及到删除重复数据,下面的两个删除重复数据方法是自己经常用的,置于用一个新表来保留distinct *然后删除 rename等方法就不提了,因为生产库是不允许让表段invaid的。
首先来张测试表吧
Create table student(name varchar2(10),sc number)
然后insert一系列数据。
Select * from student
Name sc
3dd 56
adf 45
fda 80
ffd 78
dss 95
cfe 74
gds 92
gf 99
ddd 99
adf 45
asdf 55
3dd 56
一般生产库的表段是有主键约束的,但是也不排除有些接口表存在大量重复数据,此时需要alter table tablename add primary key(no),但是add主键时会检索我们内部的数据是否存在重复值,此时就需要删除重复数据,当然生产库的表的字段肯定更复杂,但是其实不影响实际的效果。
利用虚列rowid来实现表中数据的删除
Delete from student where rowid not in (select max(rowid) from student group by
Id);
Or
Delete from student a where rowid not in (select max(rowid) from student b where a.no=b.no)
利用rowid比较方便,效率对一般的数据量都还是不错的
利用分析函数和虚列rowid删除重复数据
Delete from student where rowid in
(Select rowid from
(Select rowid,row_number()over(partition by no order by no)cn from student)b
Where cn>1)
前面的blog提到了oracle的几个分析函数,主要是针对表段中的字段先group by分组然后排名,然后保留每个分组排名的第一个即可达到删除重复数据的solution,而且在执行时间上分析函数明显优于利用rowid分组的方法。
分页查询:
很早之前接触的一个查询是查找出表中的第20行到第50行,刚开始总是想用什么什么函数来解决,其实有了一定的开发编写经验的人一看就知道是个分页查询而已。
Select * from
(select.a.* ,rownum cn from student a where rownum<=51)b
where b.cn>=19
其实也是利用rowid虚列数据建成一个含有rowid的实值cn然后嵌套即可。
Select * from
(select.a.* ,rownum cn from student a )b
where b.cn between 19 and 51
如果用这个写法做分页查询了,大家可以分别查看一下他们的执行计划,其中第一种的执行计划中有count stopkey这个主要表示在rownum时出现,当达到指定行数时oracle就停止查询,大多数情况下count stopkey 都明显高于第二个count的效率,第一个扫描明显扫需要的逻辑读少,因为内部的第一个查询只到rownum<=51就停止了。
学习oracle大半年了,还是觉得自己sql上面的很薄弱,平常也写的比较少,sql功能不是一个查询就算完事了,还要考虑到sql的执行计划 优化器 性能上做深入了解,但是如果真的要理解这些跟数据查询在sga和数据文件如何实现,然后设计到buffer cache中的管理lru列表和dirty列表如何来管理buffer cache的缓存,然后sql的解析和执行中又有硬解析 软解析,然后执行计划中又有关于索引 cluster等的具体性能上得东西,还往下面可以一直延续下去,估计写一天也不一定能写完!
奋斗吧,为oracle而狂野。
[@more@]来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25362835/viewspace-1055687/ ,如需转载,请注明出处,否则将追究法律责任。