Oracle高效分页查询

前端之家收集整理的这篇文章主要介绍了Oracle高效分页查询前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
--分页参数:size = 20 page = 2
--没有order by的查询
-- 嵌套子查询,两次筛选(推荐使用)
--SELECT *
-- FROM (SELECT ROWNUM AS rowno,t.*
-- FROM DONORINFO t
-- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
-- AND TO_DATE ('20060731','yyyymmdd')
-- AND ROWNUM <= 20*2) table_alias
-- WHERE table_alias.rowno > 20*(2-1);        --耗时0.05s

-- 一次筛选(数据量大的时候,第一次查询的数据量过大,明显比上面慢,不推荐)
--select * from(
--SELECT ROWNUM AS rowno,t.*
--FROM DONORINFO t
--WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd') AND TO_DATE ('20060731','yyyymmdd')
--) r
--where r.rowno BETWEEN 20*(2-1)+1 and 20*2;      --耗时0.46s


--有order by的查询
--嵌套子查询,两次筛选(推荐使用)
--SELECT *
--FROM (SELECT ROWNUM AS rowno,r.*
-- FROM(
-- SELECT * FROM DONORINFO t
-- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
-- ORDER BY t.BIRTHDAY desc
-- ) r
-- where ROWNUM <= 20*2 
-- ) table_alias
-- WHERE table_alias.rowno > 20*(2-1);                --耗时0.744s

-- 一次筛选(数据量大的时候,第一次查询的数据量过大,明显比上面慢,不推荐)
--select * from (
--SELECT ROWNUM AS rowno,r.*
--FROM(
--SELECT * FROM DONORINFO t
--WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
--AND TO_DATE ('20060731','yyyymmdd')
--ORDER BY t.BIRTHDAY desc
--) r
----where ROWNUM <= 20; --这里用>查不到数据 =也查不到数据 <= 或者 < 可以查到数据 
----where ROWNUM BETWEEN 20*(2-1)+1 AND 20*2; --查不到数据
----where ROWNUM <=20*2 and ROWNUM > 20*(2-1); --查不到数据
----这是因为查询时,第一条生成的rownum为1,1>20不成立,1=20也不成立,所以这条数据就作废了,依次类推,这样就查不到任何一条数据
--) t 
--where t.rowno <=20*2 and t.rowno > 20*(2-1); --可以查到数据耗时:3.924s
---- where t.rowno BETWEEN 20*(2-1)+1 AND 20*2; --可以查到数据耗时:3.919s

--采用row_number() over 分页函数
--select * 
--from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
--     from DONORINFO d
--     WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
--                             AND TO_DATE ('20060731','yyyymmdd')
-- ) p 
--where p.rownumber BETWEEN 20*(2-1)+1 AND 20*2;  --耗时0.812s

select * from (
select * 
from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
     from DONORINFO d
     WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
                             AND TO_DATE ('20060731','yyyymmdd')
 ) p 
where p.rownumber <20*2
) where rownumber > 20*(2-1);    -- 耗时0.813s

从以上探索,我们得知:

(1)ROWNUM

rownum是一个序列,是Oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类推。

当使用条件查询时,从缓冲区或数据文件中得到的第一条记录的rownum为1,不符合sql语句的条件,会被删除,下条的rownum还是1,所以上限条件必须放在子查询,而下限条件必须放在外层查询

(2)between and 和>=and <=

这两者查询效率上来说没有区别,between and 最终也是转为>= and <=

(3)Oracle通用分页格式

没有order by

SELECT *
FROM (SELECT ROWNUM AS rowno,t.*
          FROM DONORINFO t
          WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
          AND TO_DATE ('20060731','yyyymmdd')
          AND ROWNUM <= page*size) table_alias
WHERE table_alias.rowno > (page-1)*size;

有order by

SELECT *
FROM (SELECT ROWNUM AS rowno,r.*
           FROM(SELECT * FROM DONORINFO t
                    WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
                    AND TO_DATE ('20060731','yyyymmdd')
                    ORDER BY t.BIRTHDAY desc
                   ) r
           where ROWNUM <= page*size 
          ) table_alias
WHERE table_alias.rowno > (page-1)*size;

另外,我们也可以使用row_number() over函数,但是相比前面并没有什么优势。

select * 
from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
       from DONORINFO d
       WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101','yyyymmdd')
        AND TO_DATE ('20060731','yyyymmdd')
 ) p 
where p.rownumber BETWEEN size*(page-1)+1 AND page*size;

猜你在找的Oracle相关文章