rownum和rowid

区别

rownum和rowid都是伪列

rownum是根据sql查询出的结果给每行分配一个编号

rowid是物理结构上的,在每条记录insert到数据库中时,都会有一个唯一的物理记录



rownum

先看结果:

①查找前三行的数据

Select *from test where rownum<=3;

 

②查找三行以后的数据

错误:Select *from test where rownum>=3;返回为空


正解:Select *from(select rownum rn,t.* from test t)t where t.rn>=3;

 


解析:


①种,

第一行数据rownum=1,然后发现rownum<=3满足则往下走

第二行数据rownum=2,满足继续,

第三行数据rownum=3,满足继续,

第四行数据rownum=4,不满足rownum<=3,然后将此行删除,继续

第五行数据rownum=4,关键在这里rownum还等于4,意思只要rownum不满足条件,它的值就不变,不满足rownum<=3,删除此行,继续

第六行一样,一直到了最后一行。

当然这里的删除是针对返回结果集来说的,并不是把表中的数据删除

 

种:

第一行数据rownum=1,不满足删除此行,继续

第二行数据依旧rownum=1,一直到最后一行,返回结果集为空


所以要借助子查询,可以这样理解子查询的查询流程要依赖上面所述的方法,然后得到查询结果附上新的rownum


在这个子查询得到的结果表中进行过滤查询,也就是主查询,而主查询就不需要再次依赖上面的方法进行,而是直接把rownum当成字段进行过滤where t.rn>=3,没有附新的rownum


所以Select *from(select rownum rn,t.* from test t)t where t.rn>=3;的结果是

 


③经典应用,分页查询

子查询用rownum查出所有的记录,然后主查询where借助子查询的rownum过滤出需要的数据(也就是第21-30条的记录,每页10条),即让rn>=21and rn<=30(主查询)

例如:

select *from (select rownum rn, s.* from student s) where rn>=21 and rn<=30

 

为什么这里必须用子查询

不用子查询,select xxx fromxxx where rownum>=3 and rownum<=7 查询结果是空。

个人理解,擦亮眼睛,有错必究:

因为此时遍历结果集中的第一行,rownum为1,不满足rownum>=3,删除结果集中的第一行,此时rownum不动,刚才的第二行数据上移,此时rownum还是1,只不过后面的数据发生了变化。如此重复,每次都删一行,直到最后一行,返回空结果集。

 

如果满足的话,就不删除本行数据,而rownum向下移动遍历下一行且rownum值要加1


举一反三:

1.Select *from test where rownum!=4;

和①效果一样

 

2.select rownum rn,t.* from test t wheret.score>=70


如上述所示,这里的rownum是对得到的结果集重新进行了编排

 


row_number () over (order by xxx)

和rownum类似只不过是多了个排序的功能,order by默认升序

按照分数排序后取出前三行的数据,这里用主查询是得不到结果的,因为如果写成这样

select uname,usex,score, row_number () over(order by score) rn from test where rn<=3;

是不能执行的,因为rn是一个聚合函数(和rownum最大的区别),where后不能用聚合函数

所以要借助子查询:

select uname,usex,score,rn from (selectt.*,row_number () over (order by score) rnfromtest t) where rn<=3;

 


Rowid

传统的方法:

1.        创建一个临时表用distinct把原表重复的数据过滤出去

2.        用truncate清空原表

3.        把临时表的数据重新填充到原表

但表数据是亿级的,这种方法效率就很低了

create table test_tmp as select distinct* from test;

truncatetable test;

insertinto test select * from test_tmp;

 

Rowid方法:

1.        首先子查询用group by把重复的数据分到一组

2.        然后用max或者min找出其中的一行

3.        最后主查询用rowid not in把其他行删除,任务完成

delete from stu where rowid not in (select max(rowid)from stu t group by t.no, t.name, t.sex);


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值