首先我们来看一下ROWNUM:
含义解释:
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分析相关推荐

  1. Mysql Oracle Sql server 三种数据库默认端口

    ** Mysql Oracle Sql server 三种数据库默认端口 ** SQL Server默认端口号为:1433 URL:"jdbc:microsoft:SQL Server:// ...

  2. Oracle+sql+取年度,oracle SQL语句取本周本月本年的数据

    --国内从周一到周日 国外是周日到周六 select to_char(sysdate-1,'D') from dual;--取国内的星期几 去掉减一取国外的星期 --取本周时间内的数据 select ...

  3. oracle sql语句序列,Oracle SQL之 序列使用限制

    Restrictions on Sequence Values You cannot use CURRVAL and NEXTVAL in the following constructs: ■ A ...

  4. oracle sql loop merge,Oracle之存储过程和MERGE INTO语句

    一.MERGE INTO语句 1.merge into语句的功能:我们操作数据库的时候,有时候会遇到insert或者Update这种需求.我们操纵代码时至少需要写一个插入语句和更新语句并且还得单独写方 ...

  5. oracle sql执行历史,Oracle 历史SQL执行耗时查询

    Oracle 历史SQL执行耗时查询 发布时间:2020-03-02 19:56:17 来源:51CTO 阅读:474 作者:lych528 这个查询首先得理解dba_hist_sqlstat视图,也 ...

  6. oracle的 客户端工具,Oracle SQL Handler下载-Oracle数据库客户端工具5.2 官方版-东坡下载...

    Oracle数据库客户端工具是一款非常好用的Oracle数据库客户端工具.有了它,用户可以轻松导出各种数据,操作简单,使用方便,占用资源少.有这方面需要的朋友可以来下载试试! Oracle数据库客户端 ...

  7. sql字符串截取oracle,SQL Sever和Oracle截取字符串分析

    不同的数据库下截取字符串的方法函数是不同的,在sql server下用的是substring(expression, start, length),Oracle下用的是substr(expressio ...

  8. oracle sql下划线,oracle通配符?oracle like 下划线?oracle escape用法?通配符like的使用教程...

    你是否正在寻找关于oracle通配符的内容?让我把最内涵的东西奉献给你: oracle sql语言模糊查询--通配符like的使用教程 oracle在Where子句中,可以对datetime.char ...

  9. oracle sql 历史 监控,ORACLE 管理,SQL 篇--监控

    监控事例的等待 selectevent,sum    (decode(wait_Time,0,0,1))"Prev", sum(decode(wait_Time,0,1,0)) & ...

最新文章

  1. @程序员:Java平均工资再次上涨,光张年限不涨薪的我慌了!
  2. php捕获Fatal error错误与异常处理
  3. 用户关系表 存储_如何解决oracle 19c中创建用户报错的故障
  4. 用nginx TCP反向代理作mail邮件代理
  5. 设计模式——命令模式
  6. java线程main异常,‘java.lang.NoSuchMethodError:main的原因’线程中的异常“main”’...
  7. java毕业设计房产中介管理系统Mybatis+系统+数据库+调试部署
  8. 求101到200之间的素数
  9. 无需任何软件,简单修改Win7开机登陆界面背景图片
  10. 汇新云,产品经理看得见未来的地方!
  11. walking与Matlab入门教程-连接到walking机器人
  12. 戴尔将为奔驰多款车型设计专业的车载智能系统
  13. tpc-c 测试方案
  14. 远程桌面TeamViewer, 向日葵, NoMachine 和 远程控制MobaXterm软件
  15. 高通平台开发系列讲解(外设篇)TDM配置
  16. python 表示2的n次方
  17. USB3.2 Link management
  18. 主module不能引用子module资源文件
  19. 基于Python的机器学习模型对公司人员离职情况分析及预测
  20. R语言图形用户界面数据挖掘包Rattle介绍、安装、启动、介绍(Using the rattle package for data mining)

热门文章

  1. Liner(分段线性插值)
  2. 生成特定分布随机数的方法:Python seed() 函数numpy scikit-learn随机数据生成
  3. flex的12个属性
  4. FZU OJ:2230 翻翻棋
  5. Visual Studio for Mac Preview离线下载安装
  6. Android 图文混排 通过webview实现并实现点击图片
  7. git log友好显示
  8. 手写vue2的Lazyload
  9. confusion_matrix(混淆矩阵)
  10. RBAC 权限设计(转载)