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

rownum排序问题

阅读更多

rownum和排序   (以下是转载的,没有测试)
Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。
SQL> select rownum ,id,name from student order by name;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         3 200003 李三
         2 200002 王二
         1 200001 张一
         4 200004 赵四
可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询;
SQL> select rownum ,id,name from (select * from student order by name);
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200003 李三
         2 200002 王二
         3 200001 张一
         4 200004 赵四
这样就成了按name排序,并且用rownum标出正确序号(有小到大)
笔者在工作中有一上百万条记录的表,在jsp页面中需对该表进行分页显示,便考虑用rownum来作,下面是具体方法(每页显示20条):
“select * from tabname where rownum<20 order by name" 但却发现oracle却不能按自己的意愿来执行,而是先随便取20条记录,然后再order by,后经咨询oracle,说rownum确实就这样,想用的话,只能用子查询来实现先排序,后rownum,方法如下:
"select * from (select * from tabname order by name) where rownum<20",但这样一来,效率会低很多。
后经笔者试验,只需在order by 的字段上加主键或索引即可让oracle先按该字段排序,然后再rownum;方法不变:    “select * from tabname where rownum<20 order by name"

取得某列中第N大的行

select column_name from
(select table_name.*,dense_rank() over (order by column desc) rank from table_name)
where rank = &N;
 假如要返回前5条记录:

  select * from tablename where rownum<6;(或是rownum <= 5 或是rownum != 6)
假如要返回第5-9条记录:

select * from tablename
where …
and rownum<10
minus
select * from tablename
where …
and rownum<5
order by name
选出结果后用name排序显示结果。(先选再排序)

注意:只能用以上符号(<、<=、!=)。

select * from tablename where rownum != 10;返回的是前9条记录。
不能用:>,>=,=,Between...and。由于rownum是一个总是从1开始的伪列,Oracle 认为这种条件不成立。

另外,这个方法更快:

select * from (
select rownum r,a from yourtable
where rownum <= 20
order by name )
where r > 10
这样取出第11-20条记录!(先选再排序再选)

要先排序再选则须用select嵌套:内层排序外层选。
rownum是随着结果集生成的,一旦生成,就不会变化了;同时,生成的结果是依次递加的,没有1就永远不会有2!
rownum 是在查询集合产生的过程中产生的伪列,并且如果where条件中存在 rownum 条件的话,则:

1: 假如判定条件是常量,则:
只能 rownum = 1, <= 大于1 的自然数, = 大于1 的数是没有结果的;大于一个数也是没有结果的
即 当出现一个 rownum 不满足条件的时候则 查询结束 this is stop key(一个不满足,系统将该记录过滤掉,则下一条记录的rownum还是这个,所以后面的就不再有满足记录,this is stop key);

2: 假如判定值不是常量,则:

若条件是 = var , 则只有当 var 为1 的时候才满足条件,这个时候不存在 stop key ,必须进行full scan ,对每个满足其他where条件的数据进行判定,选出一行后才能去选rownum=2的行……


以下摘自《中国IT实验室》

1.在ORACLE中实现SELECT TOP N

   由于ORACLE不支持SELECT TOP语句,所以在ORACLE中经常是用ORDER BY跟ROWNUM的组合来实现SELECT TOP N的查询。

简单地说,实现方法如下所示:

SELECT 列名1...列名n FROM

    (SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n)

   WHERE ROWNUM <= N(抽出记录数)

ORDER BY ROWNUM ASC

   下面举个例子简单说明一下。

顾客表customer(id,name)有如下数据:

ID NAME

   01 first

   02 Second

   03 third

   04 forth

   05 fifth

   06 sixth

   07 seventh

   08 eighth

   09 ninth

   10 tenth

   11 last

   则按NAME的字母顺抽出前三个顾客的SQL语句如下所示:

SELECT * FROM

    (SELECT * FROM CUSTOMER ORDER BY NAME)

   WHERE ROWNUM <= 3

   ORDER BY ROWNUM ASC

   输出结果为:

ID NAME

   08 eighth

   05 fifth

   01 first

2.在TOP N纪录中抽出第M(M <= N)条记录

ROWNUM是记录表中数据编号的一个隐藏子段,所以可以在得到TOP N条记录的时候同时抽出记录的ROWNUM,然后再从这N条记录中抽取记录编号为M的记录,即使我们希望得到的结果。

从上面的分析可以很容易得到下面的SQL语句。

SELECT 列名1...列名n FROM

     (

     SELECT ROWNUM RECNO, 列名1...列名nFROM

       (SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n)

     WHERE ROWNUM <= N(抽出记录数)

   ORDER BY ROWNUM ASC

     )

   WHERE RECNO = M(M <= N)

同样以上表的数据为基础,那么得到以NAME的字母顺排序的第二个顾客的信息的SQL语句应该这样写:

   SELECT ID, NAME FROM

     (

      SELECT ROWNUM RECNO, ID, NAME FROM

        (SELECT * FROM CUSTOMER ORDER BY NAME)

         WHERE ROWNUM <= 3

         ORDER BY ROWNUM ASC )

       WHERE RECNO = 2

     结果则为:

   ID NAME

    05 fifth

3.抽出按某种方式排序的记录集中的第N条记录

   在2的说明中,当M = N的时候,即为我们的标题讲的结果。实际上,2的做法在里面N>M的部分的数据是基本上不会用到的,我们仅仅是为了说明方便而采用。

   如上所述,则SQL语句应为:

SELECT 列名1...列名n FROM

     (

      SELECT ROWNUM RECNO, 列名1...列名nFROM

        (SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n)

         WHERE ROWNUM <= N(抽出记录数)

      ORDER BY ROWNUM ASC

     )

     WHERE RECNO = N

     那么,2中的例子的SQL语句则为:

    SELECT ID, NAME FROM

      (

       SELECT ROWNUM RECNO, ID, NAME FROM

         (SELECT * FROM CUSTOMER ORDER BY NAME)

       WHERE ROWNUM <= 2

       ORDER BY ROWNUM ASC

      )

      WHERE RECNO = 2

     结果为:

   ID NAME

    05 fifth

4.抽出按某种方式排序的记录集中的第M条记录开始的X条记录

   3里所讲得仅仅是抽取一条记录的情况,当我们需要抽取多条记录的时候,此时在2中的N的取值应该是在N >= (M + X - 1)这个范围内,当让最经济的取值就是取等好的时候了的时候了。当然最后的抽取条件也不是RECNO = N了,应该是RECNO BETWEEN M AND (M + X - 1)了,所以随之而来的SQL语句则为:

   SELECT 列名1...列名n FROM

    (

     SELECT ROWNUM RECNO, 列名1...列名nFROM

      (

      SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n)

      WHERE ROWNUM <= N (N >= (M + X - 1))

    ORDER BY ROWNUM ASC

      )

     WHERE RECNO BETWEEN M AND (M + X - 1)

    同样以上面的数据为例,则抽取NAME的字母顺的第2条记录开始的3条记录的SQL语句为:

   SELECT ID, NAME FROM

     (

      SELECT ROWNUM RECNO, ID, NAME FROM

        (SELECT * FROM CUSTOMER ORDER BY NAME)

      WHERE ROWNUM <= (2 + 3 - 1)

      ORDER BY ROWNUM ASC

     )

     WHERE RECNO BETWEEN 2 AND (2 + 3 - 1)

     结果如下:

   ID NAME

    05 fifth

    01 first

   04 forth

    以此为基础,再扩展的话,做成存储过程,将开始记录数以及抽取记录数为参数,就可以轻松实现分页抽取数据。

   当然了,上面所讲的都是一些最基本的,实际应用中往往都没有这么简单,但是不管怎么说,不管复杂的应用总是由这些简单的元素构成,掌握一些最基本的方法始终是重要的。

 

分享到:
评论

相关推荐

    ROWNUM的使用技巧

    例如,如果我们希望对一个排序结果取 Top N 数据,使用 ROWNUM 存在一些问题。因为 ROWNUM 是在结果集返回之前进行排序的,因此,使用 ROWNUM 对排序结果进行 Top N 取值,可能不会达到预期的结果。 解决方案 为了...

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

    知识点 2: 分页查询中的排序问题 在分页查询中,如果在 ORDER BY 子句中指定了排序列,会出现排序列不是按照期望的顺序进行排序的问题。这是因为 Oracle 在执行 ORDER BY 操作时,会先执行 ORDER BY 语句,然后再...

    oracle rownum和distinct

    下面我们将详细地解释 ROWNUM 和 DISTINCT 的工作原理,并分析为什么它们在一起使用时会出现一些问题。 首先, lets' talk about ROWNUM。ROWNUM 是 Oracle 系统赋予查询返回的行的编号,它是从 1 开始的,这个伪...

    oracle rownum 学习

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

    oracle-rownum用法

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

    Oracle rownum.docx

    解决这个问题的方法是将ROWNUM和ORDER BY一起放入子查询,如`SELECT ROWNUM, id, name FROM (SELECT * FROM student ORDER BY name)`,这样ROWNUM将会按照name列的排序生成。 总的来说,理解并掌握Oracle中的ROWNUM...

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

    - 如果需要按照特定顺序为结果集分配 ROWNUM,则必须先进行排序,然后再计算 ROWNUM。 ```sql SELECT ROWNUM, id, name FROM (SELECT * FROM student ORDER BY name); ``` 此查询将按照 name 字段升序排列,并...

    oracle的rownum用法

    理解`ROWNUM`的工作原理对于编写高效的Oracle查询至关重要,尤其是在处理大型数据集时,能够帮助我们避免不必要的性能问题。正确使用`ROWNUM`可以让我们更好地控制查询结果的范围,从而实现更精细化的数据处理。

    oracle中rownum的用法

    为了避免排序对`ROWNUM`的影响,可以先执行排序操作,然后再使用`ROWNUM`。例如: ```sql SELECT ROWNUM, ID, NAME FROM (SELECT * FROM STUDENT ORDER BY NAME); ``` 这种写法首先按`NAME`排序,然后再对排序后的...

    mysql实现rownum和上一条,下一条功能

    1.或许有的人会用id+limit来实现上一条,下一条功能....有的业务并不是用id来排序的.那这样的方法就没效果了. 2.现在找到了生成rownum的方法,并且优化了执行速度. 3.直接上我项目里的sql,希望对大家有用.

    oracle rownum 使用技术.pdf

    然而,在对结果进行排序后使用ROWNUM获取Top N数据时,需要注意一些潜在的问题。这是因为ROWNUM在执行计划的早期阶段就被计算,而ORDER BY子句是在后期阶段才被处理。这意味着即使对数据进行了排序,ROWNUM仍然可能...

    oracle中rownum的用法及解说

    这条语句首先根据`NAME`字段对表`STUDENT`中的记录进行排序,然后计算排序后每一行的`ROWNUM`,最后返回前三行记录。 #### 四、ROWNUM在分页查询中的应用 1. **分页查询:** - 在网页展示等场景下,经常需要对...

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

    2. **排序问题**: - **解决方案**:如果排序字段有索引,则直接使用该索引进行排序。如果没有索引,建议为排序字段创建一个索引。同时,尽量避免使用复杂的排序规则(例如多个字段排序),这会增加排序的复杂度和...

    Oracle中ROWNUM的使用技巧.docx

    然而,如果需要基于特定排序获取Top N,这种方法可能会出现问题,因为ROWNUM是在查询执行过程中逐行生成的,而不是基于查询结果的排序。为了避免这个问题,可以先对查询结果进行排序,然后在外部查询中使用ROWNUM,...

    Oracle利用rownum查询出部分数据[归类].pdf

    要解决这个问题,我们可以将`ORDER BY`子句置于`WHERE`子句之前,这样`ROWNUM`的生成就会基于排序后的结果。正确的查询应该是: ```sql SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM table1 t ORDER BY AAA )...

    oracle排序

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

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

    在描述中提到的问题中,当使用`ORDER BY`对包含非唯一值的列进行排序,并结合分页查询时,发现不同页码的数据可能会有重复。这进一步证实了`ORDER BY`在Oracle中的不稳定特性。在没有唯一索引或主键约束的情况下,...

    对Oracle 排序中的几种常用排序的介绍

    4. **获取排序后的第一条数据**:可以使用子查询结合`ROWNUM`来获取排序后的第一条记录,如: ```sql select * from ( select * from perexl order by nlssort(danwei,'NLS_SORT=SCHINESE_PINYIN_M') ) C where ...

    在oracle中灵活使用Rownum和rowId

    注意:在使用 `ROWNUM` 进行查询时,如果不加任何排序操作,则返回的顺序是不确定的,因为Oracle默认不会按照特定顺序进行排序。 ##### 4. 结合ORDER BY使用ROWNUM 为了确保查询结果按照特定顺序排列,可以结合 `...

    oracle分页 排序

    - **性能问题**:使用`ROWNUM`进行分页查询时,需要注意性能问题。特别是在大数据量的情况下,如果外层查询中的`ROWNUM`限制值较高,那么内层查询可能会检索大量不必要的数据。一种改进的方法是,在子查询中添加必要...

Global site tag (gtag.js) - Google Analytics