Oracle row_number() over()解析函数高效实现分页

1.

Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用。

分页查询格式(有order by ---三层sql):

SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME ORDER BY col1) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21


分页查询格式(无order by ---两层sql):
SELECT A.*,
FROM (SELECT *,ROWNUM  AS  RN FROM TABLE_NAME WHERE RN<= 40 ) A
)
WHERE RN >= 21

其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM <= 40和RN >= 21控制分页查询的每页的范围。

上面给出的这个分页查询语句,在大多数情况拥有较高的效率。分页的目的就是控制输出结果集大小,将结果尽快的返回。在上面的分页查询语句中,这种考虑主要体现在WHERE ROWNUM <= 40这句上。

选择第21到40条记录存在两种方法,一种是上面例子中展示的在查询的第二层通过ROWNUM <= 40来控制最大值,在查询的最外层控制最小值。而另一种方式是去掉查询第二层的WHERE ROWNUM <= 40语句,在查询的最外层控制分页的最小值和最大值。这是,查询语句如下:

SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 21 AND 40

 

下面是Copy的一个Oracle分页的存储过程:

create or replace procedure KnowledgePagerCount(p_PageSize number,          --每页记录数
                  p_PageNo number,            --当前页码,从 1 开始
                  p_SqlSelect varchar2,    --查询语句,含排序部分
                  p_OutRecordCount out number,--返回总记录数
                  cur_OUT out GM.PAGER.refCursorType)
as
    v_sql varchar2(3000);
    v_count number;
    v_heiRownum number;
    v_lowRownum number;
begin
  ----取记录总数
  execute immediate p_SqlSelect into v_count;
  p_OutRecordCount := v_count;
  ----执行分页查询
  v_heiRownum := p_PageNo * p_PageSize;
  v_lowRownum := v_heiRownum - p_PageSize + 1;

  v_sql := 'SELECT *
            FROM (
                  SELECT A.*, rownum rn
                  FROM  ('|| p_SqlSelect ||') A
                  WHERE rownum <= '|| to_char(v_heiRownum) || '
                 ) B
            WHERE rn >= ' || to_char(v_lowRownum) ;
            --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn

  OPEN cur_OUT FOR  v_sql;

end KnowledgePagerCount;


2.

在刚出来工作时!当时还没接触Oracle时候,做的第一个项目用来ibatis

当时在做分页的时候用的是ibatis自带的分页功能方法queryForPaginatedList(java.lang.String id, int pageSize),

http://ivanl.iteye.com/blog/24739

http://www.iteye.com/topic/544765

这里有详细分析,ibatis并不能像hibernate那样识别数据库并调用相应的

分页策略

 

 后来改用了mysql物理分页limit ,例如     select  * from  test  limit  1 to 20
mysql 的分页是先按照条件分页得到数据后才分配行号,这点和Oracle正好相反,这也是为什么在分析函数没出来之前

用的是三层嵌套的分页方式而且效率很低。

Oracle的分页如

--第1页
SELECT ROWNUM r,t.* FROM (
   SELECT t.* FROM test     ) t
WHERE ROWNUM between 1 AND 20

 

--麻烦,效率低!


-- 用row_number() over()函数 效率变高了
select t.* from
    (select t.*,row_number()over(order by null) orderNumber from test t )t

where orderNumber between 1and 3; 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值