`
bboyuan
  • 浏览: 26170 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

浅谈Oracle中Rownum的排序和比较

阅读更多
今天,在学习Oracle的时候,碰到了一点麻烦
后来,查阅了一些资料,做了点试验。
特此记录下来,与大家分享~
我文笔一般,说的都是大白话~希望大家能看的懂


有的时候,我们经常碰见这样的需求(比如面试的时候...),要求把一个结果集排序后,取得前N条数据的值。

比如 取得某个部门中,工资最高的前10名。在SQLServer中可以通过Order by结合TOP就可以返回相应的数据。但是,在Oracle中没有top这个关键字。那么咱如何实现呢?

Oracle提供了一个rownum的伪列(pseudocolumn),用于标明返回result的次序。比如返回的第一行数据的rownum为1,第2行为2...第N行为N。



首先,我们先建立这样一张表用来做试验:

SQL> CREATE TABLE TESTSORT(id NUMBER);
 
Table created


接下来,往这个表里INSERT 10条数据(ID从1到10)

SQL> declare
  2    type int_table_type is table of int index by binary_integer;
  3    int_table int_table_type;
  4  
  5  begin
  6  
  7    for i in 1..10 loop
  8        int_table(i):=i;
  9    end loop;
 10    forall i in 1..int_table.count
 11        insert into testsort values(int_table(i));
 12  end;
 13  /
 
PL/SQL procedure successfully completed


首先,我们先来看看,每个ID以及他们相应的ROWNUM。

SQL> select id,rownum from testsort order by id;
 
        ID     ROWNUM
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          5
         6          6
         7          7
         8          8
         9          9
        10         10
 
10 rows selected


现在,我们来取一下 ID最小的前5个值

SQL> select id,rownum from testsort where rownum<=5 order by id;
 
        ID     ROWNUM
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          5


嗯嗯~看样子是正常显示了我们需要的数据。
不过先不要急,让我们再搞些“破坏”,执行下面的这几条SQL

SQL> delete from testsort where id in (1,2,3);
 
3 rows deleted
 
SQL> select id,rownum from testsort;
 
        ID     ROWNUM
---------- ----------
         4          1
         5          2
         6          3
         7          4
         8          5
         9          6
        10          7
 
7 rows selected
 
SQL> insert into testsort values(1);
 
1 row inserted
 
SQL> insert into testsort values(2);
 
1 row inserted
 
SQL> insert into testsort values(3);
 
1 row inserted
 
SQL> select id,rownum from testsort order by id;
 
        ID     ROWNUM
---------- ----------
         1          8
         2          9
         3         10
         4          1
         5          2
         6          3
         7          4
         8          5
         9          6
        10          7
 
10 rows selected


我们再执行一下,之前那条SQL

SQL> select id,rownum from testsort where rownum<=5 order by id;
 
        ID     ROWNUM
---------- ----------
         4          1
         5          2
         6          3
         7          4
         8          5


结果是显而易见的,由于2次执行SQL的ROWNUM不一致,因此不能返回正常的数据。
那为什么会这样呢,我们需要理解ORACLE是如何给ROWNUM列赋值的。
Rownum是个伪列,并不是物理存在的,我的理解是先查到结果集之后再加上去的一个列。
那按照什么规则加呢?我们用cursor的观点去看的话,应该更容易理解。

“破坏”数据之前,fetch数据的顺序是 ID=1,2,3,4,5....
因此ID 1 的ROWNUM为1 ,ID 2的ROWNUM为2..以此类推。
所以查询的结果是我们所要的。

“破坏”数据之后,由于对TABLE做了DELETE,INSERT操作,导致fetch的顺序变更了
fetch顺序是 ID=4,5,6...1,2,3 也就是说ID4是最先被取回的数据,因此他的ROWNUM是1,ID5为2,ID1,2,3分别为8,9,10。完了之后,在Order by结果集,当然这个时候再用rownum<=5来过滤的数据就是错误的了。

这个“破坏”只是打个比喻。然而,在项目中对表的CRUD操作必不可少。所以说,像这样的SQL:select id from testsort where rownum<=5 order by id; 是一个陷阱。有一种情况例外,那就是ID为PK的时候,大家可以做下实验。

好了,下面该是如何解决问题的时候了。利用子查询问题就会游刃而解了
SQL> select t.id,rownum from (select * from testsort order by id) t where rownum<=5;
 
        ID     ROWNUM
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          5


嗯...from 子查询,返回的数据已经是被Order by了的数据了。自然fetch的顺序就是符合条件的。ORDER BY DESC也是一样的。

SQL> select t.id,rownum from (select * from testsort order by id desc) t where rownum<=5;
 
        ID     ROWNUM
---------- ----------
        10          1
         9          2
         8          3
         7          4
         6          5


虽然麻烦,但是貌似目前只能这样处理,如果哪位达人有更好的办法,请帮忙指点



最后,再来说一下Rownum比较操作符的问题。
很多资料都说不支持>,>=,=,between……and,只能用以上符号(<、& lt;=、!=)
虽说不支持,但并不会报Error。只是返回的数据永远为空,原因就是根本不可能满足这样的where条件。
SQL> select t.id,rownum from (select * from testsort order by id) t 
where rownum > 5;
 
        ID     ROWNUM
---------- ----------


之前说过,取回的第1条数据它的ROWNUM肯定是1。也就是说rownum肯定是从1开始顺番。
如上面这条SQL,取回第1条数据的id为1,rownum为1,然后Oracle一看,哦 1 < 5  ~不满足条件,舍弃了。然后取第2条数据id为2,rownum还是为1,又< 5,再舍弃。以此类推,最终舍弃了所有的数据,因此没有一条满足的,这就是所谓不支持的原因。当然一些符号(如:>=,=)和1比较是没有问题的。

那么怎么解决这个问题呢?比如,需要返回满足条件的 前2~4条数据?

我们可以举一反三,利用子查询依然能够解决这个问题。
--注意要给子查询中的rownum 起别名
select * from (
  select t.id,rownum num from (select * from testsort order by id) t where rownum < 5) where num > 1;



最后这里是Oracle对Rownum的解释:Here
以上是我与大家分享的一些拙见,希望能够帮助到像我这样的Oracle新人们,更好的理解Oracle Rownum~ 欢迎达人们指正~


0
0
分享到:
评论

相关推荐

    Oracle中rownum的使用

    Oracle中rownum的使用

    ORACLE 中ROWNUM用法总结

    `ROWNUM`在Oracle中是一个强大但需谨慎使用的工具。正确理解其行为逻辑,特别是在处理比较运算符时,是至关重要的。通过合理的设计查询结构,可以充分发挥`ROWNUM`的优势,实现在大型数据集上的高效查询和分页功能。...

    对于 Oracle 的 rownum 问题

    ROWNUM是一个序列,是oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类推。如果你用&gt;,&gt;=,=,between...and这些条件,因为从缓冲区或数据文件中得到的第一条记录的...

    oracle rownum和distinct

    "Oracle 中的 ROWNUM 和 DISTINCT" Oracle 中的 ROWNUM 和 DISTINCT 是两个非常重要的关键词,它们在查询数据时发挥着至关重要的作用。然而,许多开发者在使用这两个关键词时,却常常会遇到一些不太理解的地方,...

    oracle rownum 的使用 和sqlserver有区别的!

    本文将详细介绍 Oracle 中 ROWNUM 的使用方法,并与 SQL Server 中相应的功能进行对比分析。 #### Oracle ROWNUM 基础用法 1. **ROWNUM 的默认行为:** - 在 Oracle 中,ROWNUM 默认从 1 开始计数,对于每一行...

    oracle中rownum的用法及解说

    ### Oracle中的ROWNUM使用详解 在Oracle数据库中,`ROWNUM`是一个非常有用的伪列,它可以帮助用户在查询结果集中为每一行分配一个唯一的行号。`ROWNUM`的值从1开始,并随着行的增加而递增。下面将详细介绍`ROWNUM`...

    ROWNUM的使用技巧

    ROWNUM 是 Oracle 中的一种伪列,它可以根据返回记录生成一个序列化的数字。利用 ROWNUM,我们可以生产一些原先难以实现的结果输出,但是因为它是伪列的特殊性,在使用时需要注意一些事项,以免掉入“陷阱”。 特殊...

    oracle中rownum的用法

    ### Oracle中的ROWNUM使用详解 #### 一、ROWNUM简介 在Oracle数据库中,`ROWNUM`是一个非常有用的伪列,它为查询结果中的每一行分配一个唯一的行号。这个行号从1开始,每增加一行,行号就递增1。`ROWNUM`对于数据...

    Oracle中ROWNUM的使用技巧.docx

    总之,ROWNUM在Oracle中是一种强大的工具,但它需要谨慎使用,以避免潜在的问题。理解ROWNUM的工作原理,以及如何与其他查询结构结合,是有效利用这一特性的关键。在进行复杂查询时,应始终考虑查询性能和结果的准确...

    Oracle数据库中ORDER BY排序和查询按IN条件的顺序输出

    本文将深入探讨`ORDER BY`子句在Oracle中的排序机制,以及查询时根据`IN`条件顺序输出的方法。 首先,`ORDER BY`用于指定查询结果的排序方式,可以基于一个或多个列进行升序(ASC)或降序(DESC)排序。然而,...

    oracle-rownum用法

    ROWNUM 和排序 在 Oracle 中,ROWNUM 是在取数据的时候产生的序号,所以想对指定排序的数据去指定的 ROWNUM 行数据就必须注意了。例如: ```sql SELECT ROWNUM, id, name FROM student ORDER BY name; ``` 可以...

    oracle的rownum用法

    4. 如果表中的主键是按照升序插入的,且查询中没有`GROUP BY`和`ORDER BY`子句,`ROWNUM`的顺序可能与主键的顺序一致。但这是偶然的,不是`ROWNUM`的固有特性。 5. 在子查询中使用`ROWNUM`并将其传递到外部查询中时...

    sql语句中select top n与oracle的rownum与mysql的limit用法

    sql语句中select top n与oracle的rownum与mysql的limit 取前几条数据sql简单用法

    oracle rownum 学习

    Oracle中的ROWNUM是在取数据的时候产生的序号,所以想对指定排序的数据去指定的ROWNUM行数据就必须注意了。例如: ```sql SELECT ROWNUM, ID, NAME FROM STUDENT ORDER BY NAME; ``` 可以看出,ROWNUM并不是按照NAME...

    解析oracle的rownum

    Oracle 中的 ROWNUM 是一个伪列,用于对查询返回的行进行编号,返回的第一行分配的是 1,第二行是 2,以此类推。这个伪列可以用于限制查询返回的总行数。下面我们将通过实例来详细解析 ROWNUM 的使用方法和技巧。 ...

    关于oracle的rownum

    Oracle ROWNUM 伪列详解 Oracle 的 ROWNUM 伪列是一个非常重要的概念,它对结果集加的一个伪列,即先查到结果集之后再加上去的一个列。了解 ROWNUM 的意义是非常重要的,否则可能会出现莫名其妙的结果。 ROWNUM ...

    在oracle中灵活使用Rownum和rowId

    ### 在Oracle中灵活使用Rownum和RowId 在Oracle数据库中,`ROWNUM` 和 `ROWID` 是两个非常重要的概念,它们可以帮助我们在查询数据时实现更灵活的数据管理。本文将详细介绍这两个概念的区别及其使用方法,并通过...

    Oracle rownum.docx

    总的来说,理解并掌握Oracle中的ROWNUM用法对于编写高效、精确的SQL查询至关重要。正确使用ROWNUM可以帮助我们限制返回的结果集大小,进行分页,以及在特定条件下选择行。但同时也需要注意其在不同情况下的行为差异...

    如何解决Oracle分页查询中排序与效率问题

    本文主要解决 Oracle 分页查询中排序与效率问题,通过实践和分析,提供了两种解决方案,并对比了两种方法的优缺点。 知识点 1: Oracle 分页查询的基本概念 Oracle 分页查询是指在查询结果中,通过限制行数来实现...

    oracle排序

    在 Oracle 中,可以对 ROWNUM 函数进行优化,例如,以下语句将对 perexl 表中的数据按照 出生年月 列进行排序,然后进行分页查询,并对 ROWNUM 函数进行优化: SELECT * FROM (SELECT rownum rn, t.* FROM (SELECT ...

Global site tag (gtag.js) - Google Analytics