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

          Oracle分析函數(shù)

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

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

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

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

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

          4 分區(qū)子句<query-partition-clause>的格式為:
            partition by<value_exp>[,value_expr]...
            關鍵字partition by子句根據(jù)由分區(qū)表達式的條件邏輯地將單個結(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:指定了包含空值的返回行應出現(xiàn)在有序序列中的第一個或最后一個位置。

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

          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)計的總和,同一部門總和不變
                  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按薪水高低對每個員工在本部門和整個公司內(nèi)的排名進行排序。
          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ù)的滑動窗口,該窗口的分析函數(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:相當于group by deptno
          rows 2:表示前兩行相加
          preceding:表示從每個部門的第一行開始。


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

          7 行窗口
          是物理單元,包含在窗口中的物理行數(shù)。對數(shù)據(jù)類型沒有限制。
          計算每個記錄與其之前的2個記錄的平均工資。
          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)計工資每個部門最低或最高的員工信息。
          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)計各班成績第一名的同學信息    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.在求第一名成績的時候,不能用row_number(),因為如果同班有兩個并列第一,row_number()只返回一個結(jié)果          
              2.rank()和dense_rank()的區(qū)別是:
                --rank()是跳躍排序,有兩個第二名時接下來就是第四名
                --dense_rank()l是連續(xù)排序,有兩個第二名時仍然跟著第三名

                   
            
          二:開窗函數(shù)           
                開窗函數(shù)指定了分析函數(shù)工作的數(shù)據(jù)窗口大小,這個數(shù)據(jù)窗口大小可能會隨著行的變化而變化,舉例如下: 
          1:     
             over(order by salary) 按照salary排序進行累計,order by是個默認的開窗函數(shù)
             over(partition by deptno)按照部門分區(qū)
          2:
            over(order by salary range between 5 preceding and 5 following)
             每行對應的數(shù)據(jù)窗口是之前行幅度值不超過5,之后行幅度值不超過5
             例如:對于以下列
               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                                                                 
                       
             就是說,對于aa=5的一行 ,sum為   5-1<=aa<=5+2 的和
             對于aa=2來說 ,sum=1+2+2+2+3+4=14     ;
             又如 對于aa=9 ,9-1<=aa<=9+2 只有9一個數(shù),所以sum=9    ;
                        
          3:其它:
               over(order by salary rows between 2 preceding and 4 following)
                    每行對應的數(shù)據(jù)窗口是之前2行,之后4行 
          4:下面三條語句等效:           
               over(order by salary rows between unbounded preceding and unbounded following)
                    每行對應的數(shù)據(jù)窗口是從第一行到最后一行,等效:
               over(order by salary range between unbounded preceding and unbounded following)
                     等效
               over(partition by null)
          主站蜘蛛池模板: 通道| 潼关县| 静海县| 金寨县| 丰原市| 林芝县| 桑日县| 滦平县| 临泽县| 丹寨县| 华蓥市| 利川市| 平湖市| 深州市| 乌恰县| 蓬溪县| 江北区| 双牌县| 岳西县| 南投市| 鱼台县| 新安县| 施秉县| 海原县| 江陵县| 高台县| 衡水市| 宝应县| 遂溪县| 聂荣县| 道真| 翼城县| 天长市| 鹤岗市| 韶山市| 筠连县| 平果县| 醴陵市| 河南省| 东台市| 永嘉县|