求oracle分页查询语句方案

索隆 2012-03-05 10:22:22
求oracle分页查询语句方案

oracle的分页语句我已经知道
在网上查了一下,大概都是这些:

SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A --不排序
WHERE ROWNUM <= 40
)
WHERE RN >= 21;

SELECT /*+ FIRST_ROWS */ *
FROM (SELECT a.*, row_number() over(ORDER BY 1) rn--假排序,速度同上
FROM t1 a)
WHERE rn BETWEEN 21 AND 40;

SELECT *
FROM (SELECT a.*, row_number() over(ORDER BY c1) rn --真实排序,无法比较速度
FROM t1 a)
WHERE rn BETWEEN 21 AND 40;

我想问的是:你怎么保证你下一次查询时,结果集还是按照原来查询的顺序排列的呢?
如果不能保证,那你在查询下一页内容就是不是对应上次查询的下一页内容,比如:

第一次查询,结果集是这样的:
1,a
2,b
3,c
4,d
5,f
6,e
7,f
8,g
9,h
10,i

如果用上述语句:假如结果集而是:
1,a
2,b
3,c
4,d
5,f

那我想查询下一页内容,应该是:
6,e
7,f
8,g
9,h
10,i

你怎么保证一定就是这5条呢?
它不一定还是按照第一次查询的顺序排列的啊,结果集可能是:
1,h
2,g
3,c
4,a
5,p
这个我已经实际验证过了,真的不是第一查询的顺序。
所以才会问这个问题,不知各位前辈怎么样用oracle做分页查询的?
希望赐教。
...全文
185 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
iqlife 2012-03-05
  • 打赏
  • 举报
回复
/*结论:使用rownum做分页查询,必须将rownum放在子查询内!否则不起作用!!!*/

结论明显是错误的,ROWNUM的优先级高于ORDER BY ,如果要按一定顺序排列的话,必然要ORDER BY 放在子查询里,然后再取ROWNUM
索隆 2012-03-05
  • 打赏
  • 举报
回复
刚才我又做了些实验,大家看下结果:

select b.* from
(
select t.*,rownum rr from v_view_forta t
) b
where b.rr between 5 and 8
order by b.rr

--1,13 表中group字段
020801
020801
020801
0201
0105

0310
021201
021201
021201
0306

0306
0212
021301

-- 11,13 表中group字段 ,正确
0306
0212
021301
-- 5,8 表中group字段 正确
0105
0310
021201
021201


select k.*,rownum rr from v_view_forta k
where rownum between 2 and 6
-- 1,10
0101
0101
0104
0104
0105

0105
0110
011002
011002
011002

-- 2,6 结果集为空!!!

-- 这样写结果同上
/*select g.*,rownum rr from v_view_forta g
where rownum>=3 and rownum<=10*/


select * from
(
select d.*,rownum rr from v_view_forta d
) p
where p.rr>=2 and p.rr<=7

-- 1,10
020801
020801
020801
0201
0105

0310
021201
021201
021201
0306

-- 2,7 正确
020801
020801
0201
0105
0310
021201

/*结论:使用rownum做分页查询,必须将rownum放在子查询内!否则不起作用!!!*/
这是我得出的结论,不知大家有何见解,集思广益,希望大家献计献策,感激不尽!
iqlife 2012-03-05
  • 打赏
  • 举报
回复
一般来说,用的都是第一种
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A --不排序
WHERE ROWNUM <= 40
)
WHERE RN >= 21;

按照ROWNUM来分页的话,的确有可能出现排序不一致,可能性的大小取决你表的数据被更新,删除的频度,在真实应用里的变化一般可以忽略,由于他速度最快,一般都用这个

如果一定要严格的排序的话,一般在第一种的语句上做变化,如下
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME ORDER BY ..) A --排序
WHERE ROWNUM <= 40
)
WHERE RN >= 21;

第三种的话,使用分析函数,太耗资源了,不建议这么用,尤其大数据量的前提下
索隆 2012-03-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 java3344520 的回复:]
/*结论:使用rownum做分页查询,必须将rownum放在子查询内!否则不起作用!!!*/

结论明显是错误的,ROWNUM的优先级高于ORDER BY ,如果要按一定顺序排列的话,必然要ORDER BY 放在子查询里,然后再取ROWNUM
[/Quote]如果我的结论是错误的,那怎么解释:select g.*,rownum rr from v_view_forta g
where rownum>=3 and rownum<=10查到的是空?
  • 打赏
  • 举报
回复
ROWNUM不是查询之后生成的。它是表中的一个伪列。每张表都设置了类似于ROWNUM这样的伪列。

rownum的赋值时间:
在数据库解析完查询语句之后,并且在查询语句做任何的排序或者聚合之前,ROWNUM被赋值,就是在查询的时候已经被赋值了

所以在这个基础上取的数据 看出来的效果就是数据库默认的排序效果


假设表名tb1 表字段id,no 取分组排序后的5-10条数据


select *
from (
select a.*,
row_number() over(partition by a.no order by a.id) rn
from tb1 a
)t1
where rn > 4 and rn <10


这个和rownum效果差不多 必须要在子查询里面进行排序后 才能在外层取的想要的排序后的数据

17,082

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧