Oracle-Mysql:ROWNUM函数的使⽤
对于rownum来说它是oracle系统顺序分配为从查询返回的⾏的编号,返回的第⼀⾏分配的是1,第⼆⾏是2,依此类推,这个伪字段可以⽤于限制查询返回的总⾏数,且rownum不能以任何表的名称作为前缀。
(1) rownum 对于等于某值的查询条件
如果希望到学⽣表中第⼀条学⽣的信息,可以使⽤rownum=1作为条件。但是想到学⽣表中第⼆条学⽣的信息,使⽤rownum=2结果查不到数据。因为rownum都是从1开始,但是1以上的⾃然数在rownum做等于判断是时认为都是false条件,所以⽆法查到rownum =
n(n>1的⾃然数)。
SQL> select rownum,id,name from student where rownum=1;(可以⽤在限制返回记录条数的地⽅,保证不出错,如:隐式游标)SQL> select rownum,id,name from student where rownum =2;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
(2)rownum对于⼤于某值的查询条件
如果想到从第⼆⾏记录以后的记录,当使⽤rownum>2是查不出记录的,原因是由于rownum是⼀个总是从1开始的伪列,Oracle 认为rownum> n(n>1的⾃然数)这种条件依旧不成⽴,所以查不到记录。
查到第⼆⾏以后的记录可使⽤以下的⼦查询⽅法来解决。注意⼦查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,⽆法知道rownum是⼦查询的列还是主查询的列。
SQL>select * from(select rownum no ,id,name from student) where no>2;
NO ID NAME
---------- ------ ---------------------------------------------------
3 200003 李三
4 200004 赵四
(3)rownum对于⼩于某值的查询条件
rownum对于rownum<n((n>1的⾃然数)的条件认为是成⽴的,所以可以到记录。
SQL> select rownum,id,name from student where rownum <3;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
1 200001 张⼀
2 200002 王⼆
查询rownum在某区间的数据,必须使⽤⼦查询。例如要查询rownum在第⼆⾏到第三⾏之间的数据,包括第⼆⾏和第三⾏数据,那么我们只能写以下语句,先让它返回⼩于等于三的记录⾏,然后在主查询中判断新的rownum的别名列⼤于等于⼆的记录⾏。但是这样的操作会在⼤数据集中影响速度。
SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
NO ID NAME
---------- ------ ---------------------------------------------------
2 200002 王⼆
3 200003 李三
(4)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条记录。
不能⽤:>,>=,=,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 )
oracle游标的使用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
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论