关于查询排名

先看个例子,以hr用户下的employees表为例子,查询工资金额(这里不算佣金)在第四名至第七名之间的员工的信息。
             第一种方法,利用ORACLE分析函数,我们分几步来写出这个SQL:
           1,select employee_id,first_name,last_name,salary, 
                 rank() over (order by salary desc) as rank
                from employees group by employee_id,first_name,last_name,salary;
            得到如下结果:

                 图片

                      可以看出此时的employee_id是按照salary的多少进行排序的,注意后面的rank_salary的名次是并列的(有了两个salary相同的第二名,接下来的是第四名),这个地方如果用dense_rank(),则在两个第二名后仍是第三名。
        2,进行子查询:
       select * from ( select employee_id,first_name,last_name,salary, 
                 rank() over (order by salary desc) as rank
                from employees group by employee_id,first_name,last_name,salary)  tt where tt.rank>3 and tt.rank<8;
       执行结果:

           图片

                   注意:rank函数那一列的别名万不可包含salary,它是ORACLE的关键字,使用了它,执行子查询时,总会提示这个别名标识符有误!(在sys用户名下使用select * from v$reserved_words查看关键字)

            第二种方法,介绍下ORACLE的伪列rownum
      1,我们可以使用rownum来控制查询语句返回的行数:
        select * from employees where rownum<5;

        图片

                 看到这里可能有人要问了,既然可以控制只返回前4行,那么可不可以控制返回4行以后的呢?我们来试试:
            select * from employees where rownum>5;
      返回结果:

           图片

                    很遗憾,什么都没有!这是为什么呢?这就跟rownum的性质有关了,rownum在提取行时,总是以1开始的,如果第一条不满足,那么取第二条,此时第二条又变成了1,第二条不满足,再取下一条,还是以1开始......所以,用>去检索rownum,必然是什么都检索不到。只有两种情况例外,就是当rownum>0或者rownum>=1是有结果显示的,而且是显示的所有行;当rownum=1时,只显示一行,即整个表的第一行。
        本来我们开始本想使用select .....from......order by ......where rownum>3 and rownum<8句子来实现排名工资的,现在已得知rownum不能使用>,那么是不是就没有办法了吗?我试了试这种方法:
   1,select * from (select * from employees order by salary desc) aa where rownum<8;

         图片

 

              这里补充下,可能有人会问我为什么要用上内嵌视图,为什么不写成
          select * from employees order  by salary desc where rownum<8这样执行,会报错。因为rownum的序号是在建表插入数据时系统指定的,哪行被第一个插入,哪个数据的ROWNUM就为1,举个例子,我执行如下语句:
select rownum,employee_id,first_name,first_name,salary from employees order by salary desc;

           执行结果:

          图片

           可以看出,rownum并不是我们想象的那样,取前七行就行了。而使用内嵌视图,相当于上面这个表就是源表,因为相当于新建了一张表,ROWNUM这个时候就是按EMPLOYEE_ID的顺序来排列的,然后在用rownum取前七行就行了。


               2,select * from
            (select rownum vv,employee_id,first_name,last_name,salary
             from (select * from employees order by salary desc) aa where rownum<8) bb
              where bb.vv>3;

               执行结果:

             图片

           这也是排名,从第四名到第七名的顺序,但是rownum有一个致命的问题:如有有并列的怎么办?你又怎么知道并列的行是第排rownum?所以这种排名之类的东西,还是要用分析函数写。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值