搜索
首页数据库mysql教程oracle分析函数技术详解(配上开窗函数over())

一、Oracle分析函数入门 分析函数是什么? 分析函数是Oracle专门用于 解决复杂报表统计需求 的功能强大的函数, 它可以在数据中进行分组然后计算基于组的某种统计 ,并且每一组的每一行都可以返回一个统计。 分析函数和聚合函数的不同之处是什么? 普通的聚

一、Oracle分析函数入门

分析函数是什么?
分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值。

          

分析函数和聚合函数的不同之处是什么?
普通的聚合函数用group by分组,每个分组返回一个统计值,而分析函数采用partition by分组,并且每组每行都可以返回一个统计值。

              

分析函数的形式
分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用形式如下:over(partition by xxx order by yyy rows between zzz)。
注:窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提

    

分析函数例子(在scott用户下模拟)

示例目的:显示各部门员工的工资,并附带显示该部分的最高工资。

oracle分析函数技术详解(配上开窗函数over())

<span>--</span><span>显示各部门员工的工资,并附带显示该部分的最高工资。</span><span>SELECT</span> E.DEPTNO,
       E.EMPNO,
       E.ENAME,
       E.SAL,
       LAST_VALUE(E.SAL) 
       <span>OVER</span>(PARTITION <span>BY</span> E.DEPTNO 
            <span>ORDER</span> <span>BY</span> E.SAL ROWS 
            <span>--</span><span>unbounded preceding and unbouned following针对当前所有记录的前一条、后一条记录,也就是表中的所有记录</span>            <span>--</span><span>unbounded:不受控制的,无限的</span>            <span>--</span><span>preceding:在...之前</span>            <span>--</span><span>following:在...之后</span>            <span>BETWEEN</span> UNBOUNDED PRECEDING <span>AND</span> UNBOUNDED FOLLOWING) MAX_SAL
  <span>FROM</span> EMP E;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

               

示例目的:按照deptno分组,然后计算每组值的总和

<span>SELECT</span> EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       <span>SUM</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> ENAME) max_sal
  <span>FROM</span> SCOTT.EMP;

运行结果:

oracle分析函数技术详解(配上开窗函数over())

     

示例目的:对各部门进行分组,并附带显示第一行至当前行的汇总

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       <span>--</span><span>注意ROWS BETWEEN unbounded preceding AND current row  是指第一行至当前行的汇总</span>       <span>SUM</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
                     <span>ORDER</span> <span>BY</span> ENAME 
                     ROWS <span>BETWEEN</span> UNBOUNDED PRECEDING <span>AND</span> <span>CURRENT</span> ROW) max_sal
  <span>FROM</span> SCOTT.EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

   

示例目标:当前行至最后一行的汇总

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       <span>--</span><span>注意ROWS BETWEEN current row AND unbounded following 指当前行到最后一行的汇总</span>       <span>SUM</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
                     <span>ORDER</span> <span>BY</span> ENAME 
                     ROWS <span>BETWEEN</span> <span>CURRENT</span> ROW <span>AND</span> UNBOUNDED FOLLOWING) max_sal
  <span>FROM</span> SCOTT.EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

   

 示例目标:当前行的上一行(rownum-1)到当前行的汇总

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       <span>--</span><span>注意ROWS BETWEEN 1 preceding AND current row 是指当前行的上一行(rownum-1)到当前行的汇总 </span>       <span>SUM</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
                     <span>ORDER</span> <span>BY</span> ENAME ROWS 
                     <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>CURRENT</span> ROW) max_sal
  <span>FROM</span> SCOTT.EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

    

示例目标:   当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总     

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       <span>--</span><span>注意ROWS BETWEEN 1 preceding AND 1 following 是指当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总</span>       <span>SUM</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
                     <span>ORDER</span> <span>BY</span> ENAME 
                     ROWS <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>2</span> FOLLOWING) max_sal
  <span>FROM</span> SCOTT.EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

     



二、理解over()函数

1.1、两个order by的执行时机
分析函数(以及与其配合的开窗函数over())是在整个sql查询结束后(sql语句中的order by的执行比较特殊)再进行的操作, 也就是说sql语句中的order by也会影响分析函数的执行结果:

a) 两者一致:如果sql语句中的order by满足分析函数配合的开窗函数over()分析时要求的排序,即sql语句中的order by子句里的内容和开窗函数over()中的order by子句里的内容一样,

那么sql语句中的排序将先执行,分析函数在分析时就不必再排序
b) 两者不一致:如果sql语句中的order by不满足分析函数配合的开窗函数over()分析时要求的排序,即sql语句中的order by子句里的内容和开窗函数over()中的order by子句里的内容不一样,

那么sql语句中的排序将最后在分析函数分析结束后执行排序

           

1.2、开窗函数over()分析函数中的分组/排序/窗口
      开窗函数over()分析函数包含三个分析子句:分组子句(partition by), 排序子句(order by), 窗口子句(rows)
      窗口就是分析函数分析时要处理的数据范围,就拿sum来说,它是sum窗口中的记录而不是整个分组中的记录,因此我们在想得到某个栏位的累计值时,我们需要把窗口指定到该分组中的第一行数据到当前行, 如果你指定该窗口从该分组中的第一行到最后一行,那么该组中的每一个sum值都会一样,即整个组的总和。

      窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提。


      窗口子句中我们经常用到指定第一行,当前行,最后一行这样的三个属性:
第一行是 unbounded preceding,
当前行是 current row,
最后一行是 unbounded following,

注释:

开窗函数over()出现分组(partition by)子句时,

unbounded preceding即第一行是指表中一个分组里的第一行, unbounded following最后一行是指表中一个分组里的最后一行

开窗函数over()省略了分组(partition by)子句时,

unbounded preceding即第一行是指表中的第一行, unbounded following最后一行是指表中的最后一行。


窗口子句不能单独出现,必须有order by子句时才能出现

例如:

<span>last_value(sal) <span>over</span>(partition <span>by</span> deptno 
                     <span>order</span> <span>by</span> sal 
                     rows <span>between</span> unbounded preceding <span>and</span> unbounded following)</span>

以上示例指定窗口为整个分组。而出现order by子句的时候,不一定要有窗口子句,但效果会很不一样,此时的窗口默认是当前组的第一行到当前行!


如果省略分组,则把全部记录当成一个组。
a) 如果存在order by则默认窗口是unbounded preceding and current row   --当前组的第一行到当前行
b) 如果这时省略order by则窗口默认为unbounded preceding and unbounded following  --整个组
 


而无论是否省略分组子句,如下结论都是成立的:

1、窗口子句不能单独出现,必须有order by子句时才能出现

2、当省略窗口子句时:
a) 如果存在order by则默认的窗口是unbounded preceding and current row  --当前组的第一行到当前行,即在当前组中,第一行到当前行
b) 如果同时省略order by则默认的窗口是unbounded preceding and unbounded following  --整个组

             
所以,

lag(sal) over(order by sal) 解释

over(order by salary)表示意义如下:

首先,我们要知道由于省略分组子句,所以当前组的范围为整个表的数据行,

然后,在当前组(此时为整个表的数据行)这个范围里执行排序(即order by salary),

最后,我们知道分析函数lag(sal)在当前组(此时为整个表的数据行)这个范围里的窗口范围为当前组的第一行到当前行,即分析函数lag(sal)在这个窗口范围执行。


参见:

Oracle的LAG和LEAD分析函数


Oracle分析函数ROW_NUMBER()|RANK()|LAG()使用详解


1.3、帮助理解over()的实例

例1:关注点:sql无排序,over()排序子句省略

<span>SELECT</span> DEPTNO, EMPNO, ENAME, SAL, 
       LAST_VALUE(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO)
<span>FROM</span> EMP;

运行结果:

 

oracle分析函数技术详解(配上开窗函数over())

       

例2:关注点:sql无排序,over()排序子句有,窗口省略

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       EMPNO,
       ENAME,
       SAL,
       LAST_VALUE(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
                            <span>ORDER</span> <span>BY</span> SAL <span>DESC</span>)
  <span>FROM</span> EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

 

oracle分析函数技术详解(配上开窗函数over())

                  
例3:关注点:sql无排序,over()排序子句有,窗口也有,窗口特意强调全组数据

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       EMPNO,
       ENAME,
       SAL,
       LAST_VALUE(SAL) 
       <span>OVER</span>(PARTITION <span>BY</span> DEPTNO 
            <span>ORDER</span> <span>BY</span> SAL 
            ROWS <span>BETWEEN</span> UNBOUNDED PRECEDING <span>AND</span> UNBOUNDED FOLLOWING) MAX_SAL
  <span>FROM</span> EMP;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

 

oracle分析函数技术详解(配上开窗函数over())

     
例4:关注点:sql有排序(正序),over()排序子句无,先做sql排序再进行分析函数运算

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       MGR,
       ENAME,
       SAL,
       HIREDATE,
       LAST_VALUE(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO) LAST_VALUE
  <span>FROM</span> EMP
 <span>WHERE</span> DEPTNO <span>=</span> <span>30</span>
 <span>ORDER</span> <span>BY</span> DEPTNO, MGR;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

 

oracle分析函数技术详解(配上开窗函数over())

 



例5:关注点:sql有排序(倒序),over()排序子句无,先做sql排序再进行分析函数运算

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       MGR,
       ENAME,
       SAL,
       HIREDATE,
       LAST_VALUE(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO) LAST_VALUE
  <span>FROM</span> EMP
 <span>WHERE</span> DEPTNO <span>=</span> <span>30</span>
 <span>ORDER</span> <span>BY</span> DEPTNO, MGR <span>DESC</span>;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

                

例6:关注点:sql有排序(倒序),over()排序子句有,窗口子句无,此时的运算是:sql先选数据但是不排序,而后排序子句先排序并进行分析函数处理(窗口默认为第一行到当前行),最后再进行sql排序

 

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       MGR,
       ENAME,
       SAL,
       HIREDATE,
       <span>MIN</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> SAL <span>ASC</span>) LAST_VALUE
  <span>FROM</span> EMP
 <span>WHERE</span> DEPTNO <span>=</span> <span>30</span>
 <span>ORDER</span> <span>BY</span> DEPTNO, MGR <span>DESC</span>;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> DEPTNO,
       MGR,
       ENAME,
       SAL,
       HIREDATE,
       <span>MIN</span>(SAL) <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> SAL <span>DESC</span>) LAST_VALUE
  <span>FROM</span> EMP
 <span>WHERE</span> DEPTNO <span>=</span> <span>30</span>
 <span>ORDER</span> <span>BY</span> DEPTNO, MGR <span>DESC</span>;

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

              

三、常见分析函数详解

为了方便进行实践,特将演示表和数据罗列如下:

一、创建表

<span>create</span> <span>table</span> t( 
   bill_month <span>varchar2</span>(<span>12</span>) , 
   area_code <span>number</span>, 
   net_type <span>varchar</span>(<span>2</span>), 
   local_fare <span>number</span> 
);

      

二、插入数据

oracle分析函数技术详解(配上开窗函数over())

<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5761</span>,<span>'</span><span>G</span><span>'</span>, <span>7393344.04</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5761</span>,<span>'</span><span>J</span><span>'</span>, <span>5667089.85</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5762</span>,<span>'</span><span>G</span><span>'</span>, <span>6315075.96</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5762</span>,<span>'</span><span>J</span><span>'</span>, <span>6328716.15</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5763</span>,<span>'</span><span>G</span><span>'</span>, <span>8861742.59</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5763</span>,<span>'</span><span>J</span><span>'</span>, <span>7788036.32</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5764</span>,<span>'</span><span>G</span><span>'</span>, <span>6028670.45</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5764</span>,<span>'</span><span>J</span><span>'</span>, <span>6459121.49</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5765</span>,<span>'</span><span>G</span><span>'</span>, <span>13156065.77</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200405</span><span>'</span>,<span>5765</span>,<span>'</span><span>J</span><span>'</span>, <span>11901671.70</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5761</span>,<span>'</span><span>G</span><span>'</span>, <span>7614587.96</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5761</span>,<span>'</span><span>J</span><span>'</span>, <span>5704343.05</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5762</span>,<span>'</span><span>G</span><span>'</span>, <span>6556992.60</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5762</span>,<span>'</span><span>J</span><span>'</span>, <span>6238068.05</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5763</span>,<span>'</span><span>G</span><span>'</span>, <span>9130055.46</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5763</span>,<span>'</span><span>J</span><span>'</span>, <span>7990460.25</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5764</span>,<span>'</span><span>G</span><span>'</span>, <span>6387706.01</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5764</span>,<span>'</span><span>J</span><span>'</span>, <span>6907481.66</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5765</span>,<span>'</span><span>G</span><span>'</span>, <span>13562968.81</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200406</span><span>'</span>,<span>5765</span>,<span>'</span><span>J</span><span>'</span>, <span>12495492.50</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5761</span>,<span>'</span><span>G</span><span>'</span>, <span>7987050.65</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5761</span>,<span>'</span><span>J</span><span>'</span>, <span>5723215.28</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5762</span>,<span>'</span><span>G</span><span>'</span>, <span>6833096.68</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5762</span>,<span>'</span><span>J</span><span>'</span>, <span>6391201.44</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5763</span>,<span>'</span><span>G</span><span>'</span>, <span>9410815.91</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5763</span>,<span>'</span><span>J</span><span>'</span>, <span>8076677.41</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5764</span>,<span>'</span><span>G</span><span>'</span>, <span>6456433.23</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5764</span>,<span>'</span><span>J</span><span>'</span>, <span>6987660.53</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5765</span>,<span>'</span><span>G</span><span>'</span>, <span>14000101.20</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200407</span><span>'</span>,<span>5765</span>,<span>'</span><span>J</span><span>'</span>, <span>12301780.20</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5761</span>,<span>'</span><span>G</span><span>'</span>, <span>8085170.84</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5761</span>,<span>'</span><span>J</span><span>'</span>, <span>6050611.37</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5762</span>,<span>'</span><span>G</span><span>'</span>, <span>6854584.22</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5762</span>,<span>'</span><span>J</span><span>'</span>, <span>6521884.50</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5763</span>,<span>'</span><span>G</span><span>'</span>, <span>9468707.65</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5763</span>,<span>'</span><span>J</span><span>'</span>, <span>8460049.43</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5764</span>,<span>'</span><span>G</span><span>'</span>, <span>6587559.23</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5764</span>,<span>'</span><span>J</span><span>'</span>, <span>7342135.86</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5765</span>,<span>'</span><span>G</span><span>'</span>, <span>14450586.63</span>); 
<span>insert</span> <span>into</span> t <span>values</span>(<span>'</span><span>200408</span><span>'</span>,<span>5765</span>,<span>'</span><span>J</span><span>'</span>, <span>12680052.38</span>); 
<span>commit</span>;

oracle分析函数技术详解(配上开窗函数over())

            

三、first_value()与last_value():求最值对应的其他属性
问题、取出每月通话费最高和最低的两个地区。

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> BILL_MONTH, 
       AREA_CODE,
       <span>SUM</span>(LOCAL_FARE) LOCAL_FARE, 
       FIRST_VALUE(AREA_CODE) 
       <span>OVER</span>(PARTITION <span>BY</span> BILL_MONTH 
            <span>ORDER</span> <span>BY</span> <span>SUM</span>(LOCAL_FARE) <span>DESC</span> 
            ROWS <span>BETWEEN</span> UNBOUNDED PRECEDING <span>AND</span> UNBOUNDED FOLLOWING) FIRSTVAL, 
       LAST_VALUE(AREA_CODE) 
       <span>OVER</span>(PARTITION <span>BY</span> BILL_MONTH 
            <span>ORDER</span> <span>BY</span> <span>SUM</span>(LOCAL_FARE) <span>DESC</span> 
            ROWS <span>BETWEEN</span> UNBOUNDED PRECEDING <span>AND</span> UNBOUNDED FOLLOWING) LASTVAL 
  <span>FROM</span> T 
 <span>GROUP</span> <span>BY</span> BILL_MONTH, AREA_CODE 
 <span>ORDER</span> <span>BY</span> BILL_MONTH

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

   

四、rank(),dense_rank()与row_number():求排序

rank,dense_rank,row_number函数为每条记录产生一个从1开始至n的自然数,n的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略
①row_number:
row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增
②dense_rank:
dense_rank函数返回一个唯一的值,当碰到相同数据时,此时所有相同数据的排名都是一样的
③rank:
rank函数返回一个唯一的值,当碰到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名

          

演示数据在Oracle自带的scott用户下:
1、rank()值相同时排名相同,其后排名跳跃不连续

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> <span>*</span> 
  <span>FROM</span> (<span>SELECT</span> DEPTNO, 
               RANK() <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> SAL <span>DESC</span>) RW, 
               ENAME,
               SAL
          <span>FROM</span> SCOTT.EMP) 
 <span>WHERE</span> RW <span> <span>4</span>;</span>

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())
2、dense_rank()值相同时排名相同,其后排名连续不跳跃

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> <span>*</span> 
  <span>FROM</span> (<span>SELECT</span> DEPTNO, 
               DENSE_RANK() <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> SAL <span>DESC</span>) RW, 
               ENAME,
               SAL
          <span>FROM</span> SCOTT.EMP) 
 <span>WHERE</span> RW <span> <span>4</span>;</span>

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())
3、row_number()值相同时排名不相等,其后排名连续不跳跃

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> <span>*</span> 
  <span>FROM</span> (<span>SELECT</span> DEPTNO, 
               ROW_NUMBER() <span>OVER</span>(PARTITION <span>BY</span> DEPTNO <span>ORDER</span> <span>BY</span> SAL <span>DESC</span>) RW, 
               ENAME,
               SAL
          <span>FROM</span> SCOTT.EMP) 
 <span>WHERE</span> RW <span> <span>4</span>;</span>

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

 

五、lag()与lead():求之前或之后的第N行
lag和lead函数可以在一次查询中取出同一字段的前n行的数据和后n行的值。这种操作可以使用对相同表的表连接来实现,不过使用lag和lead有更高的效率。
lag(arg1,arg2,arg3)
第一个参数是列名,
第二个参数是偏移的offset,
第三个参数是超出记录窗口时的默认值。
  
举例如下:
SQL> select *  from kkk;                                         
                                                                 
        ID NAME                                                  
---------- --------------------                                  
         1 1name                                                 
         2 2name                                                 
         3 3name                                                 
         4 4name                                                 
         5 5name                                                 
SQL> select id,name,lag(name,1,0) over(order by id) from kkk;
                                                                 
        ID NAME                 LAG(NAME,1,0)OVER(ORDERBYID)     
---------- -------------------- ----------------------------     
         1 1name                0                                
         2 2name                1name                            
         3 3name                2name                            
         4 4name                3name                            
         5 5name                4name

SQL> select id,name,lead(name,1,0) over(order by id) from kkk;
                                                                 
        ID NAME                 LEAD(NAME,1,0)OVER(ORDERBYID)    
---------- -------------------- -----------------------------    
         1 1name                2name                            
         2 2name                3name                            
         3 3name                4name                            
         4 4name                5name                            
         5 5name                0

SQL> select id,name,lead(name,2,0) over(order by id) from kkk;                                                                                                              
        ID NAME                 LEAD(NAME,2,0)OVER(ORDERBYID)    
---------- -------------------- -----------------------------    
         1 1name                3name                            
         2 2name                4name                            
         3 3name                5name                            
         4 4name                0                                
         5 5name                0 
SQL> select id,name,lead(name,1,'linjiqin') over(order by id) from kkk;                                 
                                                                                 
        ID NAME                 LEAD(NAME,1,'ALSDFJLASDJFSAF')                   
---------- -------------------- ------------------------------                   
         1 1name                2name                                            
         2 2name                3name                                            
         3 3name                4name                                            
         4 4name                5name                                            
         5 5name                linjiqin  

---------------------------------------------------------------------------------------

   

六、rollup()与cube():排列组合分组
1)、group by rollup(a, b, c):
首先会对(a、b、c)进行group by,
然后再对(a、b)进行group by,
其后再对(a)进行group by,
最后对全表进行汇总操作。

     

2)、group by cube(a, b, c):
则首先会对(a、b、c)进行group by,
然后依次是(a、b),(a、c),(a),(b、c),(b),(c),
最后对全表进行汇总操作。

   

1、生成演示数据:
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as ds_trade
 
SQL> conn system/oracle as sysdba
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0
Connected as SYS
 
SQL> create table scott.t as select * from dba_indexes;
 
Table created
 
 
SQL> connect scott/oracle
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0
Connected as scott
 
SQL>

    

2、普通group by体验
sql> select owner, index_type, status, count(*) from t where owner like 'SY%' group by owner, index_type, status;

oracle分析函数技术详解(配上开窗函数over())

3、group by rollup(A,B,C)
GROUP BY ROLLUP(A, B, C):
首先会对(A、B、C)进行GROUP BY,
然后再对(A、B)进行GROUP BY,
其后再对(A)进行GROUP BY,
最后对全表进行汇总操作。
sql> select owner, index_type, status, count(*) from t where owner like 'SY%' group by ROLLUP(owner, index_type, status);

oracle分析函数技术详解(配上开窗函数over())

4、group by cube(A,B,C)
GROUP BY CUBE(A, B, C):
则首先会对(A、B、C)进行GROUP BY,
然后依次是(A、B),(A、C),(A),(B、C),(B),(C),
最后对全表进行汇总操作。

sql> select owner, index_type, status, count(*) from t where owner like 'SY%' group by cube(owner, index_type, status);

oracle分析函数技术详解(配上开窗函数over())

  

七、max(),min(),sun()与avg():求移动的最值总和与平均值
问题:计算出各个地区连续3个月的通话费用的平均数(移动平均值)

 

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> AREA_CODE, 
       BILL_MONTH,
       LOCAL_FARE,
       <span>SUM</span>(LOCAL_FARE) <span>OVER</span>(PARTITION <span>BY</span> AREA_CODE 
                            <span>ORDER</span> <span>BY</span> TO_NUMBER(BILL_MONTH) 
                            RANGE <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>1</span> FOLLOWING) "3month_sum", 
       <span>AVG</span>(LOCAL_FARE) <span>OVER</span>(PARTITION <span>BY</span> AREA_CODE 
                            <span>ORDER</span> <span>BY</span> TO_NUMBER(BILL_MONTH) 
                            RANGE <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>1</span> FOLLOWING) "3month_avg", 
       <span>MAX</span>(LOCAL_FARE) <span>OVER</span>(PARTITION <span>BY</span> AREA_CODE 
                            <span>ORDER</span> <span>BY</span> TO_NUMBER(BILL_MONTH) 
                            RANGE <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>1</span> FOLLOWING) "3month_max", 
       <span>MIN</span>(LOCAL_FARE) <span>OVER</span>(PARTITION <span>BY</span> AREA_CODE 
                            <span>ORDER</span> <span>BY</span> TO_NUMBER(BILL_MONTH) 
                            RANGE <span>BETWEEN</span> <span>1</span> PRECEDING <span>AND</span> <span>1</span> FOLLOWING) "3month_min" 
  <span>FROM</span> (<span>SELECT</span> T.AREA_CODE, T.BILL_MONTH, <span>SUM</span>(T.LOCAL_FARE) LOCAL_FARE 
          <span>FROM</span> T 
         <span>GROUP</span> <span>BY</span> T.AREA_CODE, T.BILL_MONTH)

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

  

问题:求各地区按月份累加的通话费

oracle分析函数技术详解(配上开窗函数over())

<span>SELECT</span> AREA_CODE, 
       BILL_MONTH,
       LOCAL_FARE,
       <span>SUM</span>(LOCAL_FARE) <span>OVER</span>(PARTITION <span>BY</span> AREA_CODE 
                            <span>ORDER</span> <span>BY</span> BILL_MONTH <span>ASC</span>) "last_sum_value" 
  <span>FROM</span> (<span>SELECT</span> T.AREA_CODE, T.BILL_MONTH, <span>SUM</span>(T.LOCAL_FARE) LOCAL_FARE 
          <span>FROM</span> T 
         <span>GROUP</span> <span>BY</span> T.AREA_CODE, T.BILL_MONTH) 
 <span>ORDER</span> <span>BY</span> AREA_CODE, BILL_MONTH

oracle分析函数技术详解(配上开窗函数over())

运行结果:

oracle分析函数技术详解(配上开窗函数over())

 

--------------------------------------------------------------------------
Blog:http://www.cnblogs.com/linjiqin/
J2EE、Android、Linux、Oracle QQ交流群:142463980、158560018(满)

另见:《Oracle分析函数ROW_NUMBER()|RANK()|LAG()使用详解

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
什么是oracle asm什么是oracle asmApr 18, 2022 pm 04:16 PM

oracle asm指的是“自动存储管理”,是一种卷管理器,可自动管理磁盘组并提供有效的数据冗余功能;它是做为单独的Oracle实例实施和部署。asm的优势:1、配置简单、可最大化推动数据库合并的存储资源利用;2、支持BIGFILE文件等。

oracle怎么查询所有索引oracle怎么查询所有索引May 13, 2022 pm 05:23 PM

方法:1、利用“select*from user_indexes where table_name=表名”语句查询表中索引;2、利用“select*from all_indexes where table_name=表名”语句查询所有索引。

Oracle怎么查询端口号Oracle怎么查询端口号May 13, 2022 am 10:10 AM

在Oracle中,可利用lsnrctl命令查询端口号,该命令是Oracle的监听命令;在启动、关闭或重启oracle监听器之前可使用该命令检查oracle监听器的状态,语法为“lsnrctl status”,结果PORT后的内容就是端口号。

oracle全角怎么转半角oracle全角怎么转半角May 13, 2022 pm 03:21 PM

在oracle中,可以利用“TO_SINGLE_BYTE(String)”将全角转换为半角;“TO_SINGLE_BYTE”函数可以将参数中所有多字节字符都替换为等价的单字节字符,只有当数据库字符集同时包含多字节和单字节字符的时候有效。

oracle怎么删除sequenceoracle怎么删除sequenceMay 13, 2022 pm 03:35 PM

在oracle中,可以利用“drop sequence sequence名”来删除sequence;sequence是自动增加数字序列的意思,也就是序列号,序列号自动增加不能重置,因此需要利用drop sequence语句来删除序列。

oracle怎么查询数据类型oracle怎么查询数据类型May 13, 2022 pm 04:19 PM

在oracle中,可以利用“select ... From all_tab_columns where table_name=upper('表名') AND owner=upper('数据库登录用户名');”语句查询数据库表的数据类型。

oracle查询怎么不区分大小写oracle查询怎么不区分大小写May 10, 2022 pm 05:45 PM

方法:1、利用“LOWER(字段值)”将字段转为小写,或者利用“UPPER(字段值)”将字段转为大写;2、利用“REGEXP_LIKE(字符串,正则表达式,'i')”,当参数设置为“i”时,说明进行匹配不区分大小写。

Oracle怎么修改sessionOracle怎么修改sessionMay 13, 2022 pm 05:06 PM

方法:1、利用“alter system set sessions=修改后的数值 scope=spfile”语句修改session参数;2、修改参数之后利用“shutdown immediate – startup”语句重启服务器即可生效。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具