分析函數
分析函數是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 by和sql語句的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
