<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    Oracle分析函數

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

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

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

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

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

    4 分區子句<query-partition-clause>的格式為:
      partition by<value_exp>[,value_expr]...
      關鍵字partition by子句根據由分區表達式的條件邏輯地將單個結果集分成N組。這里的"分區partition"和"組group"
    都是同義詞。

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

    6窗口子句windowing-clause
     給出一個固定的或變化的數據窗口方法,分析函數將對這些數據進行操作。在一組基于任意變化或固定的窗口中,
    可用該子句讓分析函數計算出它的值。
    格式:
     {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:指明窗口是從分區(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 連續求和
    select deptno,ename,sal,sum(sal) over(order by ename)  連續求和 from emp;

    DEPTNO               ENAME                        SAL       連續求和
    -------------------- -------------------- ----------- ----------
    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 不連續求和
    select deptno,ename,sal,sum(sal) over()  不連續求和 from emp;

    DEPTNO               ENAME                        SAL      不連續求和
    -------------------- -------------------- ----------- ----------
    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) 連續求和,
    sum(sal) over() 總和,
    100*round(sal/sum(sal) over(),4) "份額(%)"
    from emp
    /
    DEPTNO               ENAME                        SAL       連續求和         總和      份額(%)
    -------------------- -------------------- ----------- ---------- ---------- ----------
    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.使用子分區查詢。
    按部門薪水連續的總和.
    (1)select deptno,sum(sal) over (partition by deptno order by ename) 按部門連續求總和 from emp;

    DEPTNO                       按部門連續求總和
    -------------------- ----------------
    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) 按部門連續求總和 from emp ;

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

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

    DEPTNO                        不按部門連續求總和
    -------------------- ------------------
    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) 不按部門連續求總和 from emp ;

    DEPTNO                        不按部門連續求總和
    -------------------- ------------------
    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) 部門連續求和,--各部門的薪水"連續"求和
            sum(sal) over (partition by deptno) 部門總和,   -- 部門統計的總和,同一部門總和不變
            100*round(sal/sum(sal) over (partition by deptno),4) "部門份額(%)",
            sum(sal) over (order by deptno,ename) 連續求和, --所有部門的薪水"連續"求和
            sum(sal) over () 總和,   -- 此處sum(sal) over () 等同于sum(sal),所有員工的薪水總和
            100*round(sal/sum(sal) over (),4) "總份額(%)"
            from emp;

    DEPTNO               ENAME                        SAL       部門連續求和       部門總和     部門份額(%)       連續求和         總和     總份額(%)
    -------------------- -------------------- ----------- ------------ ---------- ----------- ---------- ---------- ----------
    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按薪水高低對每個員工在本部門和整個公司內的排名進行排序。
    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
    窗口子句是數據的滑動窗口,該窗口的分析函數將窗口看成一組。
    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僅對數據值和日期類型數據有效。(sal)
     select deptno,ename,sal, count(*) over(order by sal asc range 3 preceding) 總計

    7 行窗口
    是物理單元,包含在窗口中的物理行數。對數據類型沒有限制。
    計算每個記錄與其之前的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函數可從一組中選擇每一行和最后一行
    統計工資每個部門最低或最高的員工信息。
    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 統計各班成績第一名的同學信息    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 
        --
        得到結果:
        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()只返回一個結果          
        2.rank()和dense_rank()的區別是:
          --rank()是跳躍排序,有兩個第二名時接下來就是第四名
          --dense_rank()l是連續排序,有兩個第二名時仍然跟著第三名

             
      
    二:開窗函數           
          開窗函數指定了分析函數工作的數據窗口大小,這個數據窗口大小可能會隨著行的變化而變化,舉例如下: 
    1:     
       over(order by salary) 按照salary排序進行累計,order by是個默認的開窗函數
       over(partition by deptno)按照部門分區
    2:
      over(order by salary range between 5 preceding and 5 following)
       每行對應的數據窗口是之前行幅度值不超過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)
       得出的結果是
                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一個數,所以sum=9    ;
                  
    3:其它:
         over(order by salary rows between 2 preceding and 4 following)
              每行對應的數據窗口是之前2行,之后4行 
    4:下面三條語句等效:           
         over(order by salary rows between unbounded preceding and unbounded following)
              每行對應的數據窗口是從第一行到最后一行,等效:
         over(order by salary range between unbounded preceding and unbounded following)
               等效
         over(partition by null)
    主站蜘蛛池模板: 免费国产在线观看| 女人被男人躁的女爽免费视频| 亚洲成AV人网址| 亚洲6080yy久久无码产自国产| 免费精品国产自产拍在| 亚洲午夜电影在线观看高清| 精品久久8x国产免费观看| 亚洲网站免费观看| 亚洲一区二区免费视频| 亚洲国产亚洲综合在线尤物| 啦啦啦高清视频在线观看免费| 亚洲人配人种jizz| 免费无码又爽又刺激高潮| 久久久久亚洲精品无码网址色欲| 免费国产综合视频在线看| 春暖花开亚洲性无区一区二区| 亚洲情a成黄在线观看| 中文字幕av无码不卡免费| 好看的电影网站亚洲一区| 1000部拍拍拍18免费网站| 中文字幕在线观看亚洲视频| 天天干在线免费视频| 一级做a爰片久久免费| 亚洲AV无码一区二区二三区软件| 18级成人毛片免费观看| 亚洲kkk4444在线观看| 亚洲av日韩av欧v在线天堂| 国产一级婬片A视频免费观看| 亚洲av无码一区二区三区不卡| 2020久久精品国产免费| 黄页网址在线免费观看| 亚洲成AV人片在线播放无码| 国产日本一线在线观看免费| 国产亚洲日韩在线a不卡| 精品久久久久久亚洲| 四虎国产精品免费久久| 一区在线免费观看| 亚洲第一二三四区| 亚洲福利视频一区二区| 久久精品国产免费观看三人同眠 | 四虎影视在线永久免费观看|