Oracle SQL篇(三)Oracle ROWNUM 与TOP N分析
含义解释:
1、rownum是oracle为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推。这是一个伪列,可以用于限制查询返回的总行数。
2、rownum不能以任何基表的名称作为前缀。
对于ROWNUM来说,通常我们可以使用的比较符是<和<=,不能单独的使用=、>、>=等比较运算符,其实我们可以这样简单的
理解,oracle是找到第一条的记录添加序号1之后,才可以知道谁是第二条记录,然后添加序号2,以此类推。所以对于等于来说,是可以有例外的,就是
rownum=1。
我们来看几个简单的演示:
scott@DB01> create table demo as select
demono,ename,sal,comm,deptno from demo;
Table created.
scott@DB01> select rownum,t.* from demo t;
ROWNUM
demoNO
ENAME
SAL
COMM
DEPTNO
---------- ---------- ---------- ---------- ----------
----------
1
7369
SMITH
800
20
2
7499
ALLEN
1600
300
30
3
7521
WARD
1250
500
30
4
7566
JONES
2975
20
5
7654
MARTIN
1250
1400
30
6
7698
BLAKE
2850
30
7
7782
CLARK
2450
10
8
7788
SCOTT
3000
20
9
7839
KING
5000
10
10
7844
TURNER
1500
0
30
11
7876
ADAMS
1100
20
12
7900
JAMES
950
30
13
7902
FORD
3000
20
14
7934
MILLER
1300
10
14 rows selected.
scott@DB01> select rownum,demono,ename,sal from demo
where rownum<=3;
ROWNUM
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
1
7369
SMITH
800
2
7499
ALLEN
1600
3
7521
WARD
1250
scott@DB01> select rownum,demono,ename,sal from demo
where rownum<3;
ROWNUM
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
1
7369
SMITH
800
2
7499
ALLEN
1600
scott@DB01> select rownum,demono,ename,sal from demo
where rownum=1;
ROWNUM
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
1
7369
SMITH
800
scott@DB01> select rownum,demono,ename,sal from demo
where rownum=3;
no rows selected
scott@DB01> select rownum,demono,ename,sal from demo
where rownum>3;
no rows selected
如果我们想要查询结果集中的某一段范围的记录,比如5-10条的记录,该如何查询呢?很多开发人员把这样的需求称为分页
scott@DB01> select rownum,demono,ename,sal from demo
where rownum between 5 and 10;
no rows selected
上面是一个错误的例子,我们来看正确的写法,这里我们使用到了集合运算符minus(减法运算)
scott@DB01> select rownum,demono,ename,sal from demo
where rownum<=10
2
minus
3
select rownum,demono,ename,sal from demo where
rownum<=4;
ROWNUM
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
5
7654
MARTIN
1250
6
7698
BLAKE
2850
7
7782
CLARK
2450
8
7788
SCOTT
3000
9
7839
KING
5000
10
7844
TURNER
1500
6 rows selected.
如果我们有这样一个需求,找到员工demo表中,薪水最高的前三名,如何来实现呢?在sql server中有标准的top
n分析语句,不过不要放到oracle里来使用,不同的数据库还是有区别的。当然了,也许你会认为这个问题有歧义,是前三个人呢?还是薪水排在最高3位的人?因为薪水有可能是相同的,在这里我们就找前三个人,看下面的语句:
scott@DB01> select rownum,demono,ename,sal
2> from demo
3> where rownum<=3
4> order by sal desc;
ROWNUM
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
2
7499
ALLEN
1600
3
7521
WARD
1250
1
7369
SMITH
800
这个语句从表面上来看好像是正确的,从demo表里查询数据,排序,最后利用rownum返回前三个人,但是我们看语句的执行结果显然是不正确的。对于oracle的语句,我们在执行的时候遵循top-down的顺序,或者我们可以说,语句按照顺序来执行。
当然也有个别例外:
scott@DB01> select deptno,sum(sal) from demo
2
group by deptno
3
having sum(sal)>=10000;
DEPTNO SUM(SAL)
---------- ----------
20
10875
scott@DB01> select deptno,sum(sal) from demo
2
having sum(sal)>=10000
3
group by deptno;
DEPTNO SUM(SAL)
---------- ----------
20
10875
对于前面排名的语句当然是有问题的。当第2行语句执行后,拿到表中所有的数据,第3行语句紧接着执行,就把最前面的三条记录取出来了(rownum是对查询结果添加序号),这个时候,再做排序,当然拿到的就是对前面三条记录排序的结果,如上所示。
正确的思路应该是,先做排序,再做条件筛选,也就是4行子句要在3行之前运行,如何来实现呢?在这里oracle借助了子查询,用oracle的标准表述叫做内联视图(inline
view),当然整个的sql就是oracle的top N分析语句的写法,我们来看例子:
scott@DB01> select rownum
rank,t.*
2
from (select demono,ename,sal from demo order by sal desc) t
3
where rownum<=3;
RANK
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
1
7839
KING
5000
2
7788
SCOTT
3000
3
7902
FORD
3000
在这里,oracle其实对内部子查询做了优化处理,我们通常认为,简单子查询是内层查询先执行,然后传递结果给外层查询,然后外层查询再执行。
但是对于这个例子,如果demo表数据量很大的话,那么内层排序需要花的时间就会非常多。而实际上呢,oracle会知道外层查询需要的记录数,如本例中是3,
oracle在对内层查询排序时,并不是对demo表中的14条记录做完全的排序,根据算法,他只要找到sal最高的3条就可以了,其余的11条记录是没必要排序的,这就大大的节省了语句的执行时间。
如果想要得到排序后的某段数据,我们可以通过嵌套的方法来实现:
scott@DB01> select
t1.*
2
from (select rownum rank,t.*
from (select demono,ename,sal from demo order by sal desc) t)
t1
3
where rank>=3 and rank<=7;
RANK
demoNO
ENAME
SAL
---------- ---------- ---------- ----------
3
7788
SCOTT
3000
4
7566
JONES
2975
5
7698
BLAKE
2850
6
7782
CLARK
2450
7
7499
ALLEN
1600
注:在前面两个例子中,我们使用到了oracle的top N分析,不过都是对整张表,或者整个结果集来说的。其实oracle
对于类似的操作,提供了一套函数,我们称之为分析函数,分析函数对于数据做统计和分析是非常有帮助的,我们在下面只是举一个简单的小例子,如果你感兴趣可以看看
scott@DB01> select * from demo;
demoNO
ENAME
SAL
COMM
DEPTNO
---------- ---------- ---------- ---------- ----------
7369
SMITH
800
20
7499
ALLEN
1600
300
30
7521
WARD
1250
500
30
7566
JONES
2975
20
7654
MARTIN
1250
1400
30
7698
BLAKE
2850
30
7782
CLARK
2450
10
7788
SCOTT
3000
20
7839
KING
5000
10
7844
TURNER
1500
0
30
7876
ADAMS
1100
20
7900
JAMES
950
30
7902
FORD
3000
20
7934
MILLER
1300
10
14 rows selected.
scott@DB01> break on deptno skip 1
scott@DB01> select *
2 from (select deptno,
3
ename,
4
sal,
5
dense_rank() over(partition by deptno order by sal desc) dr
6
from demo
7
)
8 where
dr<=3
9 order by deptno;
DEPTNO
ENAME
SAL
DR
---------- ---------- ---------- ----------
10
KING
5000
1
CLARK
2450
2
MILLER
1300
3
20
SCOTT
3000
1
FORD
3000
1
JONES
2975
2
ADAMS
1100
3
30
BLAKE
2850
1
ALLEN
1600
2
TURNER
1500
3
10 rows selected.
scott@DB01> select * from (
2
select deptno,
3
ename,
4
sal,
5
row_number() over(partition by deptno order by sal desc) dr
6
from demo
7
)
8 where
dr<=3
9 order by deptno;
DEPTNO
ENAME
SAL
DR
---------- ---------- ---------- ----------
10
KING
5000
1
CLARK
2450
2
MILLER
1300
3
20
SCOTT
3000
1
FORD
3000
2
JONES
2975
3
30
BLAKE
2850
1
ALLEN
1600
2
TURNER
1500
3
Oracle SQL篇(三)Oracle ROWNUM 与TOP N分析的更多相关文章
- Oracle SQL篇(一)null值之初体验
从我第一次正式的写sql语句到现在,已经超过10年的时间了.我写报表,做统计分析和财务对账,我一点点的接触oracle数据库,并尝试深入了解.这条路,一走就是10年,从充满热情,到开始厌 ...
- 安装并使用Oracle SQL Developer访问Oracle
---问题 如何安装并使用Oracle SQL Developer访问Oracle. ---步骤 Oracle SQL Developer是Oracle官方出品的免费图形化开发工具,相对SQL*Plu ...
- Oracle SQL Developer,Oracle 开发工具之toad、SQL Developer、PL/SQL Developer等比较
参考: oracle 的几个开发工具比较 因Oracle几乎是中大型商业企业数据的首选,所以比较一下常用与Oracle的工具. Oracle SQL Developer 免费,一般开发使用足矣,常用. ...
- oracle学习篇三:SQL查询
select * from emp; --1.找出部门30的员工select * from emp where deptno = 30; --2.列出所有办事员(CLERK)的姓名,变化和部门编号se ...
- Oracle SQL篇(二)oracle自连接操作
oracle 的自连接(self join)操作 对于oracle数据库来说,目前支持两套语法,一套是oracle自己的sql语法,一套是通行标准的SQL99语法,那么对于oracle的连接操 ...
- Oracle SQL篇(四)group by 分组与分组的加强 rollup
分组操作group by 和分组的强化(rollup) 分组操作和分组函数的使用,对于编写SQL语句的人来说,是最基本的概念. 我们来看下面的例子: 在这里我们使用员工表EMP scott@D ...
- Oracle Sql Developer 连接oracle
PL/Sql 初次使用需要配置文件内容,对于我这种Oracle新手来说各种配置有点凌乱,所以果断选择Sql Developer. 选择它是因为初次使用的时候它不用想PL/Sql那样配置文件,而只需要添 ...
- (转) Oracle SQL优化必要的全表扫描思路分析
大多数情况下,我们需要避免SQL在查询时进行全表扫描(FTS),但是对于必须需要进行全表扫描的情况,也可以进行一些优化处理. 即使全表扫描是检索所需数据的唯一可行方法,仍然有多种方法来提升查询性能.优 ...
- Oracle SQL tuning 步骤
Oracle SQL tuning 步骤 SQL是的全称是Structured Query Language(结构化查询语言).SQL是一个在80年代中期被使用的工业标准数据库查询语言.不要把SQL语 ...
随机推荐
- java获取当前路径的几种方法
1.利用System.getProperty()函数获取当前路径: System.out.println(System.getProperty("user.dir"));//use ...
- VlanTrunk
简单的vlan trunk的配置: 第一步:添加vlan 1 Switch>enable 2 Switch#show vlan VLAN Name Status Ports ---- ----- ...
- 【转】SQL Server 2008 新类型介绍之Date和Time
转自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/13/4344429.aspx SQL Server 2008除了 ...
- node-webkit 使用nodejs第三方C/C++插件
node-webkit 在window环境下使用C/C++插件,需要使用nw-gyp先编译.本文以编译node-expat演示操作过程: 1.安装nodejs: 最好将nodejs的执行路径添加进系统 ...
- IOS自学笔记1——学前准备
函数的声明和定义: 在标准的C编译器中,定义的函数只能调用前面已经定义的函数.若在main()函数里要调用其他方法,这时得首先在main()上面声明要调用的函数,即函数的声明. C语言中,函数的声明和 ...
- springmvc中关于静态资源的放行
参考:http://blog.csdn.net/fujiakai/article/details/52504525 方法1. 修改web.xml文件,增加对静态资源的url映射,要加在org.spri ...
- The basic introduction to MIX language and machine
reference: The MIX Computer, The MIX Introduction sets, The basic info storage unit in MIX computer ...
- 面试常用算法——Longest Palindromic Substring(最长回文子串)
第一种: public static void main(String[] args) { String s = "abcbaaaaabcdcba"; int n,m; Strin ...
- MySQL 用户登录与操作执行
一个用户可以不登录进Mysql 数据库,由两方面的因数决定 1.你是谁:也就是mysql 数据库中记录的用户名和密码,在SQL Server数据库,中只要求说明你是谁就可以登录了,可是mysql 不是 ...
- Delphi获取与设置系统时间格式,即GetLocaleInfo和SetLocaleInfo
在Delphi中,特别是在写管理系统软件时,经常要用到 FormatDateTime 以将 TDateTime 格式的日期时间转换成字符串形式的值显示或保存起来,或者用 StrToDateTime将字 ...