嘟嘟老窝

上帝给了我一双黑色的眼睛,我却用它来翻白眼......

导航

« 朱煊的Google广告... 转换其他Blog数据库到Z-Blog数据库 »

Oracle下用rownum进行分页时排序的错乱

今天早上用户打电话说系统的排序有问题,仔细看了一下,问题好像是出在ROWNUM这个函数上。

在Oracle下ROWNUM函数是对查询结果按照顺序分配自增行序号,所以很多人都利用这个特点进行分页操作,即rownum between 30 and 60,这种限制返回行数的小窍门在普通情况下都很正常,但如果要对返回结果在进行排序就变得乱套了。

如下查询:

select page.* from
( select rownum page_id,
    id,
    unit_code,
    name,
    code
FROM lb_sys_twork page
WHERE state=1
ORDER BY unit_code,
    code) Page
where page.page_id between 10
       AND 31

这是一个网上很常用的查询模式,虽然我在子查询中加入了ORDER BY unit_code,code,并限制返回记录集的第10条到30条但是返回集并没有按照我所想的那样进行排序,查其原因发现rownum page_id这个伪字段并不是在最终返回结果集中生成,而是在引用它的子查询中已经返回,如此情况,在加了order by后返回的结果集也就不是按照1,2,3。。。这样的顺序排列了。我尝试将rownum page_id放在最外层,如下:

select rownum page_id, page.* from
( select id,
    unit_code,
    name,
    code
FROM lb_sys_twork page
WHERE state=1
ORDER BY unit_code,
    code) Page
where page.page_id between 10
       AND 31

这时查询出现错误,说是找不到Page_id这个字段,我将page_id的字段别名去掉,直接用rownum来做字段,结果集为空。到这时我才恍然大悟为什么把rownum叫做伪字段,rownum是在结果集进行输出时自动加入的一列,按照这种原理,如果你用Where rownum=10来限制返回的行数,将会得到的是一个空结果集,rownum>10等等也不行。看来把rownum放在子集还是放在最外层都不行,难道没办法了吗?

还是Google帮了忙找到了这片文章,其中介绍了MINUS这个减法集合运算符,MINUS是找到两个给定的数据集合之间的差异,即找到一个数据集合,该集合的数据是仅存在于前一个数据集而后一个数据集中不存在的,相当于集合1-集合2,利用此函数,我可以让集合1返回的是前50条数据,而集合2返回的是前30条,50-30就相当于返回的第30-50的数据。查询SQL如下:

SELECT rownum,
     page.*
FROM ( select Page.*
FROM lb_sys_twork page
WHERE page.state=1
ORDER BY unit_code,
    code) Page
WHERE rownum < 50 MINUS SELECT rownum,
     page.*
FROM ( select Page.*
FROM lb_sys_twork page
WHERE page.state=1
ORDER BY unit_code,
    code) Page
WHERE rownum < 30

  • 该日志的引用地址:
  • http://www.duduwolf.com/cmd.asp?act=tb&id=74
  • 1.junnie | (home)
  • 有人说不能留言哎~狼兄……
  • 2005-4-11 19:53:07
  • 2.耶利米 | (home)
  • hi
    duduwolf
    我是WZ里的djc520
    能做个友情链接吗
    如果冇一天
  • 2005-4-11 19:53:26
  • 4.junnie | (home)
  • 呵呵,就是你楼上的,他和我是校友,他说不能留言,我就试了一下Starry
    还有,现在Winzheng论坛不能注册了,你能帮我注册个号吗?junnie就可以了。老大!Capo mafioso
    我加你QQ了,暂时没反应.....
  • 2005-4-12 0:59:26
  • 5.junnie | (home)
  • 我和他都很仰慕你呀!!Kissed
  • 2005-4-12 1:00:19
  • 6.duduwolf | (home)
  • 晕...赢政最近在调整,连域名都更换了,等调整好了我帮你注册一个吧
  • 2005-4-12 8:27:14
  • 7.junnie | (home)
  • OK,没问题,我在QQ上等你消息啊~~我的QQ名字叫“空空道人”。
  • 2005-4-12 16:14:56
  • 8.耶利米 | (home)
  • 狼兄
    做个友情链接好吗?
    如果冇一天http://jeremiah.yculblog.com/
  • 2005-4-12 17:24:12
  • 10.阿乌 | (home)
  • SELECT * FROM
    (
    SELECT A.*, rownum r
    FROM
    (
    /*SELECT *
    FROM Articles
    ORDER BY PubTime DESC*/
    ) A
    WHERE rownum <= PageUpperBound
    ) B
    WHERE r > PageLowerBound;


    --注释部分可换为任何sql语句

    在hibernate的源码里也可以看到类似的封装代码,这年头这种代码还要自己去写实在是不明智的
  • 2005-5-12 14:22:13
  • 11.廖熊 | (home)
  • 用MINUS是不行的, 因为其性能很差,数据量大点不能忍受;用rownum速度很快,但是还需要再封一层,就可基本解决排序问题,但是发现hibernate的分页排序有问题,自己写的rownum也有问题(都是在极少情况下发现的,一般都正常),看来用rownum还是不准确。
  • 2005-12-8 13:41:32
  • 13.test | (home)
  • 数据量大的话,速度怎么保证?
  • 2006-2-24 15:06:28
  • 15.怎么可能 | (home)
  • select * from (select buyer_no,buyer_uid from buyer order by buyer_uid)
    *
    ERROR at line 1:
    ORA-00907: missing right parenthesis
    子查询里能用order by ???????
  • 2006-12-7 15:37:07
  • 16.风飞雪 | (home)
  • 能帮我看看我这个SQL吗,我有点菜,不好意思啊
    QQ:7858311
  • 2008-1-28 17:35:06
  • 17.风飞雪 | (home)
  • select S.* from (select t.*,ROWNUM as my_rownum from c_download t WHERE ROWNUM<=" + String.valueOf(endIndex)+" and t.ttype='one' order by DDATE desc) S";
    sql += (" where S.my_rownum>=" + String.valueOf(beginIndex));
  • 2008-1-28 17:36:11

反向链接列表

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

<< 2008·1 >>

Sun

Mon

Tue

Wen

Thu

Fri

Sat

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

Search

Powered By Z-Blog 1.4 SP1 Build 50824 - modify by duduwolf

Copyright 1999-2005 duduwolf.com Some Rights Reserved.