select count(*) from order_detail_info;
前提:Oracle是使用rownum分页,它是一个伪列,用于标记行号。下面就使用rownum进行分页查询(错误示范):
select * from order_detail_info where rownum>=2 and rownum <= 8;
执行sql之后发现并无查询结果集,这是为什么?rownum相当于一个动态的伪列,它总是从1开始,而查询条件是rownum>=2,第一条记录不满足条件,排除第一条记录以后,第二条记录的rownum又变成了1,依次类推,所以永远不能满足rownum>2这个条件,这也就是查询不到结果的原因。那么正确的用法就是先将rownum查询出来作为单独的一列,然后再添加判断条件即可。
select t.*
from (select rownum rn, o2.*
from order_detail_info o2
where o2.register_id = '437577094') t
where t.rn between 2 and 6
--耗时0.031s
select t.*
from (select rownum rn, o2.*
from order_detail_info o2
where o2.register_id = '437576875' and rownum<=6) t
where t.rn>=2
--耗时0.016s
这里要着重说明:从sql执行耗时来看,使用<= >分页方式的查询效率普遍比使用between and的效率要高。原因如下:对于方式二的分页查询,rownum<=6可以被oracle推入到内层循环中,一旦查询结果不满足rownum<=6,就终止查询将结果返回了,也就是说最内层内存查询出了6条满足条件的数据;而对于方式一的查询,由于查询条件between 2 and 6是存在于最外层,它的最内层是查询所有满足条件的数据(查询出的数据可能很多),只是在最外层做了条件筛选,显然这个效率要比方式二低很多。日常使用推荐方式二。
如果我们想要实现又要排序,又有分页的功能,例3.1的查询结果按照order_deatil_id进行排序。做法是先在内层循环排序,然后再进行分页筛选,只是比不带分页的查询多嵌套了一层。
select tt.*
from (select rownum rn, t.*
from (select o2.*
from order_detail_info o2
where o2.register_id = '437576875'
order by o2.order_detail_no desc) t
where rownum <= 6) tt
where tt.rn >= 2
面试题:每个部门工资前三高的员工。
这里使用Oracle的row_number() OVER (PARTITION BY COL1 ORDER BY COL2)函数,该函数表示根据COL1分组,在分组内部根据COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号。它与rownum的区别在于:使用rownum进行排序的时候是先将伪列加入结果集然后在排序;而此函数在包含排序从句后是先排序再计算行号码。
select deptno, ename, sal
from (select deptno,
ename,
sal,
row_number() over(partition by deptno order by sal desc) as sal_order
from scott.emp)
where sal_order <= 3;
问题描述:公司项目有一个查询会员信息的功能,数据来源于会员表,会员表中有一个字段叫会员等级,其值为三省、四星、五星、普通会员。该查询功能首先是按照会员等级进行排序,然后再分页,问题就出现了,在页面上点击分页查看信息时,会发现其中某两页的数据有重复。定位问题,发现是在排序和分页一起使用时,所排序的列必须具有唯一性,因为会员等级会有重复,所以导致查询出的结果也会有重复数据。解决办法:按照具有唯一性属性的列排序。做个记录。
参考文章:
原文:https://blog.csdn.net/u011278012/article/details/52024843
原文:https://blog.csdn.net/imliuqun123/article/details/79535871