分析函數和開窗函數


分析函數
  分析函數是Oracle專門用於解決復雜報表統計需求的功能強大的函數,它可以在數據中進行分組然后計算基於組的某種統計值,並且每一組的每一行都可以返回一個統計值

分析函數和聚合函數的區別
  普通的聚合函數用group by分組,每個分組返回一個統計值
  分析函數采用partition by分組,並且每組每行都可以返回一個統計值

  顯而易見的區別是,從返回結果上看:
  聚合后的記錄數可能會減少,因為它對數據源進行了group by操作,所以對結果是有影響的,即返回的結果里去掉聚合的列后,跟聚合前的結果不一樣
  而分析后的記錄數是不變的,因為它的作用僅僅在於分析,所以不會對結果有影響,即返回的結果里去掉分析的列后,跟分析前的結果是一樣的

分析函數的形式
  分析函數要與開窗函數(over())一起使用,使用形式為:分析函數() over()

開窗函數(over())

  開窗函數(over())包含三個分析子句:
    分組子句(partition by)
    排序子句(order by)
    窗口子句(rows)

  開窗函數(over())使用形式如下:
    over(partition by xxx order by yyy rows between zzz)

  開窗函數里的"",即"窗口",表示分析函數分析時要處理的數據范圍
  比如分析函數sum(),它所針對的數據范圍為窗口中的記錄,而不是整個表的記錄
  要獲取某個范圍的sum值,則需在窗口指定具體的數據范圍
  比如指定該窗口從該分組中的第一行到最后一行,那么該組中的每一個sum值都會一樣,即整個組的總和

  窗口子句除了rows方式的窗口,還包括range方式和滑動窗口


  排序子句(order by)

    排序子句的使用方法跟sql中的order by一樣,如:order by colA desc, colB asc nulls first, colC  nulls last
    開窗函數的order bysql語句的order by的執行時機
      分析及開窗函數是在整個sql查詢結束后再進行的, sql語句的order by也會影響分析函數的執行結果,有以下兩種情況:
        1) 兩者一致,即sql語句中的order by語句與開窗函數的order by一致,則sql語句中的order by先執行,分析函數在分析時就不必再排序
        2) 兩者不一致,即sql語句中的order by語句與開窗函數的order by不一致,則分析及開窗函數先分析排序,sql語句中的order by再最后執行

  窗口子句(rows)
    如果沒有窗口子句(rows),則默認當前組的第一行到當前行

    無論是否省略分組子句,都有:
      窗口子句(rows)不能單獨存在,必須有order by子句時才能出現
      相反,有order by子句,可以沒有窗口子句(rows)

    當省略窗口子句時
      如果存在order by,則默認的窗口是unbounded preceding and current row,即當前組的第一行到當前行
      如果不存在order by,則默認的窗口是unbounded preceding and unbounded following,即整個組

    例如:lag(sal) over(order by sal)
    over(order by salary)表示意義如下:
      1) 由於省略分組子句,所以當前組的范圍為整個表的數據行
      2) 在當前組(此時為整個表的數據行)這個范圍里執行排序,即order by salary
      3) 分析函數lag(sal)在當前組(此時為整個表的數據行)這個范圍里的窗口范圍為當前組的第一行到當前行,即分析函數lag(sal)在這個窗口范圍執行

      

    窗口子句(rows)的相關關鍵字:
    preceding:表示在...之前
      1 preceding:表示當前記錄的前1條記錄
      2 preceding:表示當前記錄的前2條記錄
      n preceding:表示當前記錄的前n條記錄
      unbounded preceding:不受控制的,無限的,
                   若無分組,則表示所有記錄的第1條記錄
                   若有分組,則表示分組后,組內的第1條記錄

    following:表示在...之后
      1 following:表示當前記錄的后一條記錄
      2 following:表示當前記錄的后兩條記錄
      n following:表示當前記錄的后n條記錄
      unbounded following:不受控制的,無限的,
                若無分組,則表示所有記錄的最后一條記錄
                若有分組,則表示分組后,組內的最后一條記錄

    相關用例:
      rows between unbounded preceding and unbounded following:針對所有記錄
      rows between unbounded preceding and current row:針對第一條記錄到當前記錄
      rows between current row and unbounded following:針對當前記錄到最后一條記錄
      rows between 1 preceding and current row:針對當前記錄的上一行記錄到當前行記錄
      rows between current row and 3 following:針對當前記錄到當前行記錄的后三條記錄
      rows between 1 preceding and 2 following:針對當前記錄的上一條記錄 ~~ 當前行記錄的后兩條記錄

    當開窗函數over()出現分組(partition by)子句時
      unbounded preceding即表中一個分組里的第一行,unbounded following即表中一個分組里的最后一行
    當開窗函數over()省略了分組(partition by)子句時
      unbounded preceding即表中的第一行, unbounded following即表中的最后一行


    使用示例:

 

select t.id,
       t.name,
       t.city,
       t.sales,
       --按城市分組,且組內銷量升序排列,並獲取當前記錄針對上一條記錄到下一條記錄范圍內的最小銷量值
       min(t.sales) over(partition by t.city order by t.sales rows between 1 preceding and 1 following) as col1,
       --按城市分組,且組內銷量升序排列,並獲取當前記錄針對第一條記錄到當前記錄范圍內的最小銷量值
       min(t.sales) over(partition by t.city order by t.sales rows between unbounded preceding and current row) as col2,
       --按城市分組,且組內銷量升序排列,並獲取當前記錄針對上三條記錄到當前記錄范圍內的最小銷量值
       min(t.sales) over(partition by t.city order by t.sales rows between 3 preceding and current row) as col3
from dataset t

 

 

 

 
        

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM