• ORACLE的rownum用法讲解


    如果选择踏足,终有一天你会爱上这条路。

    今天讲讲ORACLE中关于ROWNUM的用法:

    一、简单介绍一下ROWNUM是什么,可以用来干什么。

    答:ROWNUM是一个序列,会根据sql语句自动给你加上一列排好顺序的序号列。For example!

    你有一张全班同学的各科目成绩表。

    1、然后你想给这张表按语文成绩加上排名。你会怎么做?

    SELECT G.ID, G.NAME, G.CHINESE, ROWNUM AS CHINESE_SORT, G.MATH, G.ENGLISH

      FROM (SELECT * FROM GRADE ORDER BY CHINESE) G

     

    如果对所有科目成绩加上排名序号列呢?

    提示一下这回要用到left join了,left join会在下一篇文章中讲解。先看下面sql代码:

    SELECT *

      FROM (SELECT T.NAME,

                   T.CHINESE,

                   T1.CHINESE_SORT AS CHINESE_SORT,

                   T.MATH,

                   T2.MATH_SORT    AS MATH_SORT,

                   T.ENGLISH,

                   T3.ENGLISH_SORT AS ENGLISH_SORT

              FROM GRADE T

              LEFT JOIN (SELECT G1.NAME, G1.CHINESE, ROWNUM CHINESE_SORT

                          FROM (SELECT g.NAME, g.CHINESE

                                  FROM GRADE g

                                 ORDER BY g.CHINESE DESC) G1) T1

                ON T1.NAME = T.NAME

              LEFT JOIN (SELECT G2.NAME, G2.MATH, ROWNUM MATH_SORT

                          FROM (SELECT g.NAME, g.MATH

                                  FROM GRADE g

                                 GROUP BY g.NAME, g.MATH

                                 ORDER BY g.MATH DESC) G2) T2

                ON T2.NAME = T.NAME

              LEFT JOIN (SELECT G3.NAME, G3.ENGLISH, ROWNUM ENGLISH_SORT

                          FROM (SELECT g.NAME, g.ENGLISH

                                  FROM GRADE g

                                 GROUP BY g.NAME, g.ENGLISH

                                 ORDER BY g.ENGLISH DESC) G3) T3

                ON T3.NAME = T.NAME) MyGrade

     ORDER BY MyGrade.CHINESE_SORT;

    执行代码后结果如下图所示

     

    二、上面的内容主要讲解了ROWNUM的排序,是rownum最基本最直接的用法。不过rownum最常见的用法是用来做分页。

    还是那张成绩变:

    1、只显示前语文成绩前十名的学生记录

    select g.* from grade g where rownum < 10 order by chinese;

     

    很简单有没有。

    2、想知道语文成绩第10名以后的学生记录:

    select g.* from grade g where rownum > 10 order by chinese;

    是这样吗?执行一下,并没有结果。

    原因:文章开头说ROWNUM是一个序列,会根据sql语句自动给你加上一列排好顺序的序号列。

    rownum总是为满足条件的记录从1开始设序号,所以rownum总是从1开始的。这理解起来并没有问题哈。当从数据库中找到语文成绩第一名的记录时,设序号为1,该记录不满足rownum>10。所以抛弃该记录,接着从数据库中找到语文成绩第二名的记录,又设序号为1,该记录依然不满足rownum>10,依次类推。所以穷尽整张表抛弃了所有记录。

    正确的sql应该这样写:

    select MyGrade.*

      from (select G.*, rownum rn

              from (select g.* from grade g order by chinese) G ) MyGrade

     where MyGrade.rn >= 10;

    先select所有记录并按语文成绩排好序,外套一个select加上序号列。这就为所有记录固定好了排序的顺序。再外套一个select取出从序号>=10 的所有记录;

     

    3、获取第语文成绩有潜力提升到高分阶段的批次记录,比如第6名到第10名的记录:

    select MyGrade.*

      from (select G.*, rownum rn

              from (select g.* from grade g order by chinese) G

             where rownum <= 10) MyGrade

     where MyGrade.rn >= 6;

     

     当然,下面这段sql也可以实现同样的效果:

    select MyGrade.*

      from (select G.*, rownum rn

              from (select g.* from grade g order by chinese) G

             where rownum <= 10) MyGrade

     where MyGrade.rn >= 6 and MyGrade.rn <= 10;

    不过当数据量很大时,这段代码性能就次了好多,因为它要先遍历所有记录,然后根据序号分页。而对于之前的代码,由于CBO优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率,所以只是遍历了rownum小于10的记录,就停止了内层查询。所以推荐使用第一种分页方法。

    好了,rownum先讲到这里。如果有需要会在之后的文章中补充。下一篇文章讲解inner join、left join和right join的区别和使用。

  • 相关阅读:
    MySQL改变表的存储引擎
    数字三角形合集
    POJ 3250 Bad Hair Day 单调栈
    Linux 网卡驱动学习(二)(网络驱动接口小结)
    Lecture Notes: Macros
    [转]LNMP环境下的Web常见问题排查(精品)
    ssh-copy-id password
    python
    python
    Ceph
  • 原文地址:https://www.cnblogs.com/jxldjsn/p/8633943.html
Copyright © 2020-2023  润新知