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条记录。
不能用:>,>=,=,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
以此为基础,再扩展的话,做成存储过程,将开始记录数以及抽取记录数为参数,就可以轻松实现分页抽取数据。
ROW_NUMBER()
说明:返回结果集分区内行的序列号,每个分区的第一行从 1 开始。
语法:ROW_NUMBER () OVER ([ <partition_by_clause>]<order_by_clause> ) 。
备注:ORDERBY 子句可确定在特定分区中为行分配唯一 ROW_NUMBER 的顺序。
参数:<partition_by_clause> :将FROM 子句生成的结果集划入应用了 ROW_NUMBER 函数的分区。
<order_by_clause>:确定将 ROW_NUMBER 值分配给分区中的行的顺序。
返回类型:bigint 。
rownum详解的更多相关文章
- (转)Spring JdbcTemplate 方法详解
Spring JdbcTemplate方法详解 文章来源:http://blog.csdn.net/dyllove98/article/details/7772463 JdbcTemplate主要提供 ...
- jqGrid APi 详解
jqGrid APi 详解 jqGrid皮肤 从3.5版本开始,jqGrid完全支持jquery UI的theme.我们可以从http://jqueryui.com/themeroller/下载我们所 ...
- 【转】jqGrid 各种参数 详解
[原文]http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.htmljqGrid 各种参数 详解 JQGrid JQGrid是一个 ...
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
- oracle tkprof 工具详解
oracle tkprof 工具详解 今天是2013-09-26,进行tkprof工具使用学习,在此记录一下笔记: 一)查看需要跟踪会话信息: select s.sid,s.serial#,s.us ...
- 53个Oracle语句优化规则详解(转)
Oracle sql 性能优化调整 1. 选用适合的ORACLE优化器 ORACLE的优化器共有3种:a. RULE (基于规则) b. COST (基于成本) c. CHOOSE ...
- 常用Oracle分析函数详解 [http://www.cnblogs.com/benio/archive/2011/06/01/2066106.html]
学习步骤:1. 拥有Oracle EBS demo 环境 或者 PROD 环境2. copy以下代码进 PL/SQL3. 配合解释分析结果4. 如果网页有点乱请复制到TXT中查看 /*假设一个经理 ...
- 懵懂oracle之存储过程3--JOB详解
在前面学习了存储过程的开发.调试之后,我们现在就需要来使用存储过程了.简单的使用,像上篇<懵懂oracle之存储过程2>中提到的存储过程调用,我们可以将写好的存储过程在另一个PL/SQL块 ...
- 【Jquery系列】JqGrid参数详解
1 概述 本篇文章主要与大家分享JqGrid插件参数问题. 2 参数详解 2.1 初始化参数 2.2 ColModel参数 3 json数据 jqGrid可支持的数据类型:xml.jso ...
随机推荐
- Redis实现之整数集合
整数集合 整数集合(insert)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现.举个栗子,如果我们创建一个只包含五个 ...
- complex类的定义、实现
复数类complex的定义.实现(求模.复数加法) #include <iostream> #include <cmath> using namespace std; clas ...
- 如何使用PowerShell管理Windows服务
[TechTarget中国原创] 作为一名系统管理员,最常见的任务之一就是学会管理Windows服务,这是保证Windows服务器和客户端正常运行的重要内容. 许多操作系统和应用程序都依赖于这些服务. ...
- Locust性能测试框架学习
1. Locust简介 Locust是使用Python语言编写实现的开源性能测试工具,简洁.轻量.高效,并发机制基于gevent协程,可以实现单机模拟生成较高的并发压力. 官网:https://loc ...
- 【Part1】用JS写一个Blog(node + vue + mongoDB)
学习JS也有一段时间了,准备试着写一个博客项目,前后端分离开发,后端用node只提供数据接口,前端用vue-cli脚手架搭建,路由也由前端控制,数据异步交互用vue的一个插件vue-resourse来 ...
- JavaScript: 理解对象
ECMA-262 把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.” 严格来讲,这就相当于说对象是一组没有特定顺序的值.对象的每个属性或者方法都有一个名字,而每个名字都映射到一个值 ...
- 用Excel的分列功能格式化时间
从数据库导出的时间是带有毫秒的,怎么变成短的时间呢? 首先在时间列后面插入一列: 第二,点击数据菜单,点击分列,下一步,然后输入分割符号,然后就变成了两列.
- python 使用入的坑
如测试代码,并没有将li.li_ 的交集查询出来 li=[1,2,3,4,5] li_=[2,5,6,7,9] for i in li_: if i in li: li_.remove(i) prin ...
- 生产环境下yum的配置
介绍在局域网里面配置本地yum源环境: 在私有云的服务器上配置本地yum源 在局域网中有多台服务器,网段为192.168.10.0/24在其中一台10.11配置本地yum源,其他服务器中的baseur ...
- eclipse中xml文件报错异常处理
最近一个Javaweb工程中常出现xml文件的xsd验证失败信息,异常如下: <?xml version="1.0" encoding="UTF-8"?& ...