转自:https://blog.csdn.net/qiuzhi__ke/article/details/78892822

关于rownum是怎么产生的(网上有不少的文章,下面是摘录):

rownum是在where条件过滤之后,在任何排序(order by)或聚集(aggregation)之前赋给行的。同时,只有当rownum被分配给行后才会递增。rownum的初始值为1。rownum在查询中产生后就不再变化:

select * from emp where ROWNUM <= 5 order by sal desc;

该语句的目的是想返回top 5薪水最高的员工信息,但根据rownum的产生原理,rownum在order by之前就已经产生,所以该语句并不能起到top 5的作用,正确的语法如下:

select * from (select * from emp order by sal desc) where ROWNUM <= 5;

rownum是Oracle的一个伪列,它的顺序根据从表中获取记录的顺序递增,这里要注意的是:由于记录在表中是无序存放的,因此你无法通过简单的rownum和order by的组合获得类似TOP N的结果。

因为ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说rownum 是对符合条件结果的序列号。它总是从1开始排起的。所以你选出的结果不可能没有1,而有其他大于1的值。

如果你想获得像top n那样的结果,必须使用子查询:

select * from (select * from test order by id) where rownum<=5;

如果你想获得第5行到第10行之间的数据,则必须再加一层子查询:

select T.* from (select t.*,rownum rn from (select * from test order by id) t where rownum<=10) T where T.rn>5;

其实上面的写法是由陷阱的,不信你把order by id换成order by name

你会惊奇的发现id=4这条数据出现在了两个地方,这不合逻辑!但事实就是这样的,为什么呢?因为name不唯一,两次排序取出的结果有可能会不一样,我还是举个例子吧:

select id,name,rank() over(order by name) from test;

ID NAME                RANK()OVER(ORDERBYNAME)

---------- -------------------- -----------------------

        1 A                                          1

        2 B                                          2

        6 C                                          3

        3 C                                          3

        4 C                                          3

        8 C                                          3

        5 C                                          3

        7 C                                          3

        9 D                                          9

        10 D                                          9

从上面的结果我们不难发现,根据name排序,有多条数据并列排在第3位,这样,当取前5名时,到底在并列第3中取哪几位就不是确定的事,因此就出现了之前出现的诡异的问题。那么,怎样才能彻底解决这个问题呢?其实只要在order by name后面加上rowid,保证不会出现并列的情况就可以了

排序列不唯一所带来的问题

如果用来排序的列不唯一,也就是存在值相等的行,可能会造成第一次在前10条返回记录中,某行数据出现了,而第二次在11到第20条记录中,某行数据又出现了。一条数据重复出现两次,就必然意味着有数据在两次查询中都不会出现。

 

 其实造成这个问题的原因很简单,是由于排序列不唯一造成的。Oracle这里使用的排序算法不具有稳定性,也就是说,对于键值相等的数据,这种算法完成排序后,不保证这些键值相等的数据保持排序前的顺序。

 

 解决这个问题其实也很简单。有两种方法可以考虑。

1)在使用不唯一的字段排序时,后面跟一个唯一的字段。

一般在排序字段后面跟一个主键就可以了,如果表不存在主键,跟ROWID也可以。这种方法最简单,且对性能的影响最小。

2)另一种方法就是使用前面给出过多次的BETWEEN AND的方法。

这种方式由于采用表数据的全排序,每次只取全排序中的某一部分数据,因此不会出现上面提到的重复数据问题。

但是正是由于使用了全排序,而且ROWNUM信息无法推到查询内部,导致这种写法的执行效率很低

分页查询格式1

在查询的最外层控制分页的最小值和最大值。查询语句如下:  

SELECT * FROM 

(

SELECT A.*, ROWNUM RN 

FROM (SELECT * FROM TABLE_NAME) A 

)

WHERE RN BETWEEN 21 AND 40

分页查询格式2 

SELECT * FROM 

(

SELECT A.*, ROWNUM RN 

FROM (SELECT * FROM TABLE_NAME) A 

WHERE ROWNUM <= 40

)

WHERE RN >= 21

分页查询格式3

考虑到多表联合的情况,如果不介意在系统中使用HINT的话,可以将分页的查询语句改写为: 

SELECT /*+ FIRST_ROWS */ * FROM 

(

SELECT A.*, ROWNUM RN 

FROM (SELECT * FROM TABLE_NAME) A 

WHERE ROWNUM <= 40

)

WHERE RN >= 21

效率问题

 对比这两种写法,绝大多数的情况下,第2个查询的效率比第1个高得多。

分页查询格式4

利用row_number()函数

SELECT  *

FROM    (

        SELECT  t.*, ROW_NUMBER() OVER (ORDER BY paginator, id) AS rn

        FROM    mytable t

        )

WHERE   rn BETWEEN 900001 AND 900010

分页查询格式5

SELECT  *

FROM    (

        SELECT  t.*, ROWNUM AS rn

        FROM    (

                SELECT  * FROM mytable ORDER BY paginator, id

                ) t

        )

WHERE   rn >= 900001

        AND rownum <= 10

oracle中row_number()

1、row_number() over (order by col_1[,col_2 ...])

按照col_1[,col_2 ...]排序,返回排序后的结果集,并且为每一行返回一个不相同的值。

2、row_number() over (partition by col_n[,col_m ...] order by col_1[,col_2 ...])

先按照col_n[,col_m ...进行分组,再在每个分组中按照col_1[,col_2 ...]进行排序(升序),最后返回排好序后的结果集

row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。 与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪劣rownum然后再进行排序,而row_number()在包含排序从句后是先排序再计算行号码。

其他参考:

oracle中rownum和row_number()

http://www.jb51.net/article/65960.htm

oracle中row_number和rownum的区别和联系(翻译)

https://www.cnblogs.com/jcz1206/p/4378076.html

oracle关于rownum的使用【oracle】的更多相关文章

  1. ORACLE 中ROWNUM用法总结(转)

    ORACLE 中ROWNUM用法总结! 对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between...and,只能用以上符号(<.<=.!=) ...

  2. 【Oracle】oracle中rownum的说明及使用技巧

    oracle中常用到ROWNUM,所以做一些本人对rownum的一些认识和使用技巧的记录,以便备查. 一.rownum的说明 rownum是oracle特有的一个关键字. (1)对于基表,在inser ...

  3. oracle之rownum(伪列)

    整理和学习了一下网上高手关于rownum的帖子: 参考资料:  http://tech.ddvip.com/2008-10/122490439383296.html 和 http://tenn.jav ...

  4. Oracle中rownum和rowid的理解(转)

    本文转自地址http://www.linuxidc.com/Linux/2012-04/58300.htm rownum,rowid都叫伪列. 但是,rownum是逻辑上的编号,且其值总是从1开始,每 ...

  5. oracle 中 rownum 和 row_number()

    简单的介绍下oracle 中rownum 和 row_number() 使用,实例演示. 参照:http://www.cnblogs.com/zjrstar/archive/2006/08/31/49 ...

  6. oracle中rownum和rowid的区别

    rownum和rowid的区别总括: rownum和rowid都是伪列,但是两者的根本是不同的. rownum是根据sql查询出的结果给每行分配一个逻辑编号,所以你的sql不同也就会导致最终rownu ...

  7. ORACLE 中ROWNUM用法总结!

    ORACLE 中ROWNUM用法总结! 对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between...and,只能用以上符号(<.<=.!=) ...

  8. [转]ORACLE 中ROWNUM用法总结!

    原文地址:http://www.itpub.net/thread-824147-1-1.html 对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between ...

  9. oracle 分页(rownum的理解) 以及 树节点的查询

    1:什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条rownum=1, 第二条=2. 对于 O ...

  10. Oracle的rownum原理和使用

    整理和学习了一下网上高手关于rownum的帖子: 参考资料:  http://tech.ddvip.com/2008-10/122490439383296.html 和 http://tenn.jav ...

随机推荐

  1. 2019-2020-1 20199328《Linux内核原理与分析》第八周作业

    笔记部分 2019/11/4 17:55:22 elf文件代码默认加载到0x8048000,然后是一段首部信息,然后到达程序的真实入口 正常的系统调用会先进入内核态->用户态->系统调用下 ...

  2. Makefile 头文件 <> 与 "" 的差别,与 Visual Studio 不同

    #include "" : 首先在所有被编译的.c所在的路径中,查找头文件,如果找不到,则到 -I路径下去找头文件 #inclue <> :首先在-I路径下去找,如果找 ...

  3. Golang-filepath使用

    Golang-filepath 使用 获取当前目录 os.GetPWD() filepath.Abs(path) # 绝对目录 filepath.Dir(path) # 相对目录 可以 filepat ...

  4. MongoDB学习(三)

    MongoDB条件操作符 $gt  > 大于 $lt   < 小于 $gte >= 大于等于 $lte  <= 小于等于 $ne  !=  不等于 条件操作符可用于查询语句中, ...

  5. JavaScript 后台获取数据 - HTTP203 Advent(中文字幕)

    如果关注过 Google 相关的开发技术,对 HTTP203 这个栏目应该不陌生. 这是 HTTP203 圣诞节的特别版! Jake(@jaffathecake)和 Surma(@DasSurma)有 ...

  6. Nodejs与Mysql交互实现(异步写法,同步写法)

    https://blog.csdn.net/think_A_lot/article/details/93498737

  7. POJ 1176 Party Lamps&& USACO 2.2 派对灯(搜索)

    题目地址 http://poj.org/problem?id=1176 题目描述 在IOI98的节日宴会上,我们有N(10<=N<=100)盏彩色灯,他们分别从1到N被标上号码. 这些灯都 ...

  8. codeforce 272E Dima and Horses (假DFS)

    E. Dima and Horses Dima came to the horse land. There are n horses living in the land. Each horse in ...

  9. SpringCloudStream学习(三)RabbitMQ中的惰性队列

    ​ 从RabbitMQ 3.6.0之后,有了 Lazy Queues 的概念-一个会尽早的将队列中的内容移动到磁盘的队列,并且只有当消费者需要的时候,才会将它们加载到内存中 ​ 惰性队列设计的一个主要 ...

  10. python学习之组成字符串的两种方式

    第一种就是加法,比如 a ='张三' b = '李四' 那么print c =a+b 例如之前提到的 或者数值转换成字符串的 num  = 100 str(num) 其他参照表格中的转换即可 2.组成 ...