posts - 40, comments - 58, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Oracle分析函數(shù)

          Posted on 2009-01-20 11:33 Astro.Qi 閱讀(918) 評(píng)論(0)  編輯  收藏 所屬分類: Oracle

          分析函數(shù)
            它是Oracle分析函數(shù)專門針對(duì)類似于"經(jīng)營(yíng)總額"、"找出一組中的百分之多少" 或"計(jì)算排名前幾位"等問題設(shè)計(jì)的。
          分析函數(shù)運(yùn)行效率高,使用方便。
            分析函數(shù)是基于一組行來計(jì)算的。這不同于聚集函數(shù)且廣泛應(yīng)用于OLAP環(huán)境中。
            Oracle從8.1.6開始提供分析函數(shù),分析函數(shù)用于計(jì)算基于組的某種聚合值,它和聚合函數(shù)的不同之處是
          對(duì)于每個(gè)組返回多行,而聚合函數(shù)對(duì)于每個(gè)組只返回一行。 

          語法:
          <analytic-function>(<argument>,<argument>,...)
          over(
            <query-partition-clause>
            <order-by-clause>
            <windowing-clause>
          )
          其中:
          1 over是關(guān)鍵字,用于標(biāo)識(shí)分析函數(shù)。

          2 <analytic-function>是指定的分析函數(shù)的名字。Oracle分析函數(shù)很多。

          3 <argument>為參數(shù),分析函數(shù)可以選取0-3個(gè)參數(shù)。

          4 分區(qū)子句<query-partition-clause>的格式為:
            partition by<value_exp>[,value_expr]...
            關(guān)鍵字partition by子句根據(jù)由分區(qū)表達(dá)式的條件邏輯地將單個(gè)結(jié)果集分成N組。這里的"分區(qū)partition"和"組group"
          都是同義詞。

          5 排序子句order-by-clause指定數(shù)據(jù)是如何存在分區(qū)內(nèi)的。其格式為:
           order[siblings]by{expr|position|c_alias}[asc|desc][nulls first|nulls last]
          其中:
          (1)asc|desc:指定了排列順序。
          (2)nulls first|nulls last:指定了包含空值的返回行應(yīng)出現(xiàn)在有序序列中的第一個(gè)或最后一個(gè)位置。

          6窗口子句windowing-clause
           給出一個(gè)固定的或變化的數(shù)據(jù)窗口方法,分析函數(shù)將對(duì)這些數(shù)據(jù)進(jìn)行操作。在一組基于任意變化或固定的窗口中,
          可用該子句讓分析函數(shù)計(jì)算出它的值。
          格式:
           {rows|range}
           {between
            {unbounded preceding|current row |<value_expr>{preceding|following}
           }and
           {unbounded preceding|current row |<value_expr>{preceding|following}
           }|{unbounded preceding|current row |<value_expr>{preceding|following
           }}
          (1)rows|range:此關(guān)鍵字定義了一個(gè)window。
          (2)between...and...:為窗品指一個(gè)起點(diǎn)和終點(diǎn)。
          (3)unbounded preceding:指明窗口是從分區(qū)(partition)的第一行開始。
          (4)current row:指明窗口是從當(dāng)前行開始。

          create table emp(
           deptno varchar2(20),--部門編碼
           ename varchar2(20),--人名
           sal number(10));--工資

          insert into emp values('10','andy1',2000);
          insert into emp values('10','andy2',3000);
          insert into emp values('10','andy3',2000);
          insert into emp values('20','leno1',4000);
          insert into emp values('20','leno2',8000);
          insert into emp values('20','leno3',6000);
          insert into emp values('30','jack1',5000);
          insert into emp values('30','jack2',6000);
          insert into emp values('30','jack3',7000);

          1 連續(xù)求和
          select deptno,ename,sal,sum(sal) over(order by ename)  連續(xù)求和 from emp;

          DEPTNO               ENAME                        SAL       連續(xù)求和
          -------------------- -------------------- ----------- ----------
          10                   andy1                       2000       2000
          10                   andy2                       3000       5000
          10                   andy3                       2000       7000
          30                   jack1                       5000      12000
          30                   jack2                       6000      18000
          30                   jack3                       7000      25000
          20                   leno1                       4000      29000
          20                   leno2                       8000      37000
          20                   leno3                       6000      43000


          2 不連續(xù)求和
          select deptno,ename,sal,sum(sal) over()  不連續(xù)求和 from emp;

          DEPTNO               ENAME                        SAL      不連續(xù)求和
          -------------------- -------------------- ----------- ----------
          10                   andy1                       2000      43000
          10                   andy2                       3000      43000
          10                   andy3                       2000      43000
          20                   leno1                       4000      43000
          20                   leno2                       8000      43000
          20                   leno3                       6000      43000
          30                   jack1                       5000      43000
          30                   jack2                       6000      43000
          30                   jack3                       7000      43000

          3.
          select deptno,ename,sal,
          sum(sal) over(order by ename) 連續(xù)求和,
          sum(sal) over() 總和,
          100*round(sal/sum(sal) over(),4) "份額(%)"
          from emp
          /
          DEPTNO               ENAME                        SAL       連續(xù)求和         總和      份額(%)
          -------------------- -------------------- ----------- ---------- ---------- ----------
          10                   andy1                       2000       2000      43000       4.65
          10                   andy2                       3000       5000      43000       6.98
          10                   andy3                       2000       7000      43000       4.65
          30                   jack1                       5000      12000      43000      11.63
          30                   jack2                       6000      18000      43000      13.95
          30                   jack3                       7000      25000      43000      16.28
          20                   leno1                       4000      29000      43000        9.3
          20                   leno2                       8000      37000      43000       18.6
          20                   leno3                       6000      43000      43000      13.95


          4.使用子分區(qū)查詢。
          按部門薪水連續(xù)的總和.
          (1)select deptno,sum(sal) over (partition by deptno order by ename) 按部門連續(xù)求總和 from emp;

          DEPTNO                       按部門連續(xù)求總和
          -------------------- ----------------
          10                               2000
          10                               5000
          10                               7000
          20                               4000
          20                              12000
          20                              18000
          30                               5000
          30                              11000
          30                              18000

          (2)按部門求總和
          select deptno,sum(sal) over (partition by deptno) 按部門連續(xù)求總和 from emp ;

          DEPTNO                       按部門求總和
          -------------------- ----------------
          10                               7000
          10                               7000
          10                               7000
          20                              18000
          20                              18000
          20                              18000
          30                              18000
          30                              18000
          30                              18000

          (3)不按部門連續(xù)求總和
          select deptno,sum(sal) over (order by deptno,ename) 不按部門連續(xù)求總和 from emp ;

          DEPTNO                        不按部門連續(xù)求總和
          -------------------- ------------------
          10                                 2000
          10                                 5000
          10                                 7000
          20                                11000
          20                                19000
          20                                25000
          30                                30000
          30                                36000
          30                                43000

          (4)不按部門,求所有員工總和,效果等同于sum(sal)
          select deptno,sum(sal) over (order by deptno,ename) 不按部門連續(xù)求總和 from emp ;

          DEPTNO                        不按部門連續(xù)求總和
          -------------------- ------------------
          10                                 2000
          10                                 5000
          10                                 7000
          20                                11000
          20                                19000
          20                                25000
          30                                30000
          30                                36000
          30                                43000

          (5)select deptno,ename,sal,
                  sum(sal) over (partition by deptno order by ename) 部門連續(xù)求和,--各部門的薪水"連續(xù)"求和
                  sum(sal) over (partition by deptno) 部門總和,   -- 部門統(tǒng)計(jì)的總和,同一部門總和不變
                  100*round(sal/sum(sal) over (partition by deptno),4) "部門份額(%)",
                  sum(sal) over (order by deptno,ename) 連續(xù)求和, --所有部門的薪水"連續(xù)"求和
                  sum(sal) over () 總和,   -- 此處sum(sal) over () 等同于sum(sal),所有員工的薪水總和
                  100*round(sal/sum(sal) over (),4) "總份額(%)"
                  from emp;

          DEPTNO               ENAME                        SAL       部門連續(xù)求和       部門總和     部門份額(%)       連續(xù)求和         總和     總份額(%)
          -------------------- -------------------- ----------- ------------ ---------- ----------- ---------- ---------- ----------
          10                   andy1                       2000         2000       7000       28.57       2000      43000       4.65
          10                   andy2                       3000         5000       7000       42.86       5000      43000       6.98
          10                   andy3                       2000         7000       7000       28.57       7000      43000       4.65
          20                   leno1                       4000         4000      18000       22.22      11000      43000        9.3
          20                   leno2                       8000        12000      18000       44.44      19000      43000       18.6
          20                   leno3                       6000        18000      18000       33.33      25000      43000      13.95
          30                   jack1                       5000         5000      18000       27.78      30000      43000      11.63
          30                   jack2                       6000        11000      18000       33.33      36000      43000      13.95
          30                   jack3                       7000        18000      18000       38.89      43000      43000      16.28

          (6)TOP-N查詢
          6.1查詢各部門中工資最高的記錄
          select * from(select deptno,ename,sal,row_number() over(partition by deptno order by sal desc) topn from emp)  where topn=1;

          DEPTNO               ENAME                        SAL       TOPN
          -------------------- -------------------- ----------- ----------
          10                   andy2                       3000          1
          20                   leno2                       8000          1
          30                   jack3                       7000          1

          6.2按薪水高低對(duì)每個(gè)員工在本部門和整個(gè)公司內(nèi)的排名進(jìn)行排序。
          select deptno,ename,sal,dense_rank() over(partition by deptno order by sal desc nulls last) as dept_ranking,
              dense_rank() over(order by sal desc nulls last) as company_ranking 
          from emp;

          DEPTNO               ENAME                        SAL DEPT_RANKING COMPANY_RANKING
          -------------------- -------------------- ----------- ------------ ---------------
          20                   leno2                       8000            1               1
          30                   jack3                       7000            1               2
          20                   leno3                       6000            2               3
          30                   jack2                       6000            2               3
          30                   jack1                       5000            3               4
          20                   leno1                       4000            3               5
          10                   andy2                       3000            1               6
          10                   andy1                       2000            2               7
          10                   andy3                       2000            2               7

          5 窗口windows
          窗口子句是數(shù)據(jù)的滑動(dòng)窗口,該窗口的分析函數(shù)將窗口看成一組。
          select deptno "部門ID",ename "部門名稱",sal "工資",
              sum(sal) over(partition by deptno order by ename rows 2 preceding) "sliding total"
          from emp order by deptno,ename;

          partition by deptno:相當(dāng)于group by deptno
          rows 2:表示前兩行相加
          preceding:表示從每個(gè)部門的第一行開始。


          6 范圍窗口
          Range windows僅對(duì)數(shù)據(jù)值和日期類型數(shù)據(jù)有效。(sal)
           select deptno,ename,sal, count(*) over(order by sal asc range 3 preceding) 總計(jì)

          7 行窗口
          是物理單元,包含在窗口中的物理行數(shù)。對(duì)數(shù)據(jù)類型沒有限制。
          計(jì)算每個(gè)記錄與其之前的2個(gè)記錄的平均工資。
          set numformat 9999
          select ename,sal,
              avg(sal) over(order by deptno asc rows 2 preceding) avgasc,
              count(*) over(order by deptno asc rows 2 preceding) cntasc,
              avg(sal) over(order by deptno desc rows 2 preceding) avgdes,
              count(*) over(order by deptno desc rows 2 preceding) cntdes
          from emp order by deptno;  

          ENAME                        SAL     AVGASC     CNTASC     AVGDES     CNTDES
          -------------------- ----------- ---------- ---------- ---------- ----------
          andy1                       2000       2000          1 3666.66666          3
          andy2                       3000       2500          2 5666.66666          3
          andy3                       2000 2333.33333          3 2333.33333          3
          leno1                       4000       3000          3 5333.33333          3
          leno2                       8000 4666.66666          3 6333.33333          3
          leno3                       6000       6000          3       6000          3
          jack1                       5000 6333.33333          3       5500          2
          jack2                       6000 5666.66666          3       6000          1
          jack3                       7000       6000          3       6000          3

          8 確定每組中的第一行或最后一行
          使用first_vale和last_value函數(shù)可從一組中選擇每一行和最后一行
          統(tǒng)計(jì)工資每個(gè)部門最低或最高的員工信息。
          select deptno,ename,sal,first_value(ename) over(partition by deptno order by sal asc) as min_sal_has 
          from emp
          order by deptno,ename;

          select deptno,ename,sal,first_value(ename) over(partition by deptno order by sal desc) as min_sal_has 
          from emp
          order by deptno,ename;

          9 統(tǒng)計(jì)各班成績(jī)第一名的同學(xué)信息    NAME   CLASS S                         
              ----- ----- ---------------------- 
              fda    1      80                     
              ffd    1      78                     
              dss    1      95                     
              cfe    2      74                     
              gds    2      92                     
              gf     3      99                     
              ddd    3      99                     
              adf    3      45                     
              asdf   3      55                     
              3dd    3      78              
             
              通過:   
              --
              select * from                                                                       
              (                                                                            
              select name,class,s,rank()over(partition by class order by s desc) mm from t2
              )                                                                            
              where mm=1 
              --
              得到結(jié)果:
              NAME   CLASS S                       MM                                                                                        
              ----- ----- ---------------------- ---------------------- 
              dss    1      95                      1                      
              gds    2      92                      1                      
              gf     3      99                      1                      
              ddd    3      99                      1          
             
              注意:
              1.在求第一名成績(jī)的時(shí)候,不能用row_number(),因?yàn)槿绻嘤袃蓚€(gè)并列第一,row_number()只返回一個(gè)結(jié)果          
              2.rank()和dense_rank()的區(qū)別是:
                --rank()是跳躍排序,有兩個(gè)第二名時(shí)接下來就是第四名
                --dense_rank()l是連續(xù)排序,有兩個(gè)第二名時(shí)仍然跟著第三名

                   
            
          二:開窗函數(shù)           
                開窗函數(shù)指定了分析函數(shù)工作的數(shù)據(jù)窗口大小,這個(gè)數(shù)據(jù)窗口大小可能會(huì)隨著行的變化而變化,舉例如下: 
          1:     
             over(order by salary) 按照salary排序進(jìn)行累計(jì),order by是個(gè)默認(rèn)的開窗函數(shù)
             over(partition by deptno)按照部門分區(qū)
          2:
            over(order by salary range between 5 preceding and 5 following)
             每行對(duì)應(yīng)的數(shù)據(jù)窗口是之前行幅度值不超過5,之后行幅度值不超過5
             例如:對(duì)于以下列
               aa
               1
               2
               2
               2
               3
               4
               5
               6
               7
               9
             
             sum(aa)over(order by aa range between 2 preceding and 2 following)
             得出的結(jié)果是
                      AA                       SUM
                      ---------------------- ------------------------------------------------------- 
                      1                       10                                                      
                      2                       14                                                      
                      2                       14                                                      
                      2                       14                                                      
                      3                       18                                                      
                      4                       18                                                      
                      5                       22                                                      
                      6                       18                                                                
                      7                       22                                                                
                      9                       9                                                                 
                       
             就是說,對(duì)于aa=5的一行 ,sum為   5-1<=aa<=5+2 的和
             對(duì)于aa=2來說 ,sum=1+2+2+2+3+4=14     ;
             又如 對(duì)于aa=9 ,9-1<=aa<=9+2 只有9一個(gè)數(shù),所以sum=9    ;
                        
          3:其它:
               over(order by salary rows between 2 preceding and 4 following)
                    每行對(duì)應(yīng)的數(shù)據(jù)窗口是之前2行,之后4行 
          4:下面三條語句等效:           
               over(order by salary rows between unbounded preceding and unbounded following)
                    每行對(duì)應(yīng)的數(shù)據(jù)窗口是從第一行到最后一行,等效:
               over(order by salary range between unbounded preceding and unbounded following)
                     等效
               over(partition by null)
          主站蜘蛛池模板: 新兴县| 大名县| 金乡县| 绥德县| 仁布县| 抚顺市| 资源县| 左贡县| 亳州市| 卫辉市| 滕州市| 师宗县| 扎囊县| 陇南市| 柞水县| 旬阳县| 郸城县| 固阳县| 汽车| 富源县| 武隆县| 林甸县| 阿拉尔市| 岑溪市| 临汾市| 贵阳市| 翼城县| 台山市| 灯塔市| 洪江市| 赤壁市| 崇文区| 公安县| 雅江县| 西吉县| 溧水县| 广宗县| 涟水县| 广丰县| 金乡县| 耒阳市|