1. 程式人生 > >Oracle 分析函式(11G)語法詳解(轉)

Oracle 分析函式(11G)語法詳解(轉)

1、分析函式,最早是從ORACLE8.1.6開始出現的,它的設計目的是為了解決諸如“累計計算”,“找出分組內百分比”,“前-N條查詢”,“移動平均數計算”"等問題。其實大部分的問題都可以用PL/SQL解決,但是它的效能並不能達到你所期望的效果。分析函式是SQL言語的一種擴充,它並不是僅僅試程式碼變得更簡單而已,它的速度比純粹的SQL或者PL/SQL更快。現在這些擴充套件已經被納入了美國國家標準化組織SQL委員會的SQL規範說明書中。

2、在日常的生產環境中,我們接觸得比較多的是OLTP系統(即OnlineTransaction Process),這些系統的特點是具備實時要求,或者至少說對響應的時間多長有一定的要求;其次這些系統的業務邏輯一般比較複雜,可能需要經過多次的運算。比如我們經常接觸到的電子商城。

在這些系統之外,還有一種稱之為OLAP的系統(即Online Aanalyse Process),這些系統一般用於系統決策使用。通常和資料倉庫、資料分析、資料探勘等概念聯絡在一起。這些系統的特點是資料量大,對實時響應的要求不高或者根本不關注這方面的要求,以查詢、統計操作為主。
Oracle分析函式,主要用於OLAP的系統中

二、Oracle分析函式原理

1、分析函式通過將行分組後,再計算這些分組的值。它們與聚集函式不同之處在於能夠對每一個分組返回多行值。分析函式根據analytic claues(分析子句)將行分組,一個分組稱為:一個視窗(可通過Windowsing Clause子句進行控制)

,並通過分析語句定義,對於每一行都對應有一個在行上滑動的視窗。該視窗確定當前行的計算範圍。視窗大小可以用多個物理行(例如:rowid實際編號)進行度量,也可以使用邏輯區間進行度量,比如時間。

2、分析函式是查詢中除需要在最終處理的order by 子句之外最後執行的操作。所有連線、WHERE、GROUP BY、HAVING子句都是分析函式處理之前完成的。因此,分析函式只出現在SELECT LIST或ORDER BY(按…排序)語句中,而不能出現在where或having子句中

3、分析函式通常用於計算:資料累積值、資料移動值、資料中間值,和輸出集合報表。


三、Oracle分析函式的語法


Analytic-Function(<Argument>,<Argument>,…) 
over(
       <Query-Partition-Clause>
       <Order-by-Clause>
       <Windowing-Clause>


例如:sum(sal) over(partition by deptno order by ename)new_alias
1)sum:就是函式名
2)(sal): 是分析函式的引數,每個函式有0~3個引數,引數可以是表示式,例如:sum(sal+comm)
3)over:是一個關鍵字,用於標識分析函式,否則查詢分析器不能區別sum()聚集函式和sum()分析函式
4)partition by deptno:是可選的分割槽子句,如果不存在任何分割槽子句,則全部的結果集可看作一個單一的大區
5)order by ename:是可選的order by 子句,有些函式需要它,有些則不需要。依靠已排序資料的那些函式,例如:用於訪問結果集中前一行和後一行的LAG和LEAD,它們就必須使用;其它函式,例如:AVG,則不需要用到order by 子句。在使用了任何排序的開窗函式時,該子句是強制性的,它指定了在計算分析函式時一組內的資料是如何排序的.(即:如果要使用Windowing-Clause子句,那麼一定要先使用Order by 子句)

1、Analytic-Function


ORACLE提供了28個分析函式(包括如下:
AVG *,CORR *,COVAR_POP *,COVAR_SAMP *,COUNT*,CUME_DIST,DENSE_RANK,FIRST,FIRST_VALUE *,LAG,LAST,LAST_VALUE *,LEAD,MAX *,
MIN *,NTILE,PERCENT_RANK,PERCENTILE_CONT,PERCENTILE_DISC,RANK,RATIO_TO_REPORT,REGR_(Linear Regression) Functions *,ROW_NUMBER,STDDEV *,STDDEV_POP *,STDDEV_SAMP*,SUM *,VAR_POP *,VAR_SAMP*,VARIANCE)
,按功能分5類

1)分析函式分類
(1)等級(ranking)函式:用於尋找前N種查詢,如:RANK、DENSE_RANK等
(2)開窗(windowing)函式:用於計算不同的累計,如:SUM,COUNT,AVG,MIN,MAX等,作用於資料的一個視窗上
例如:如下函式
sum(t.sal) over (order by t.deptno,t.ename) running_total,
sum(t.sal) over (partition by t.deptno order by t.ename) department_total
(3)製表(reporting)函式:與開窗函式同名,作用於一個分割槽或一組上的所有列
例如:如下函式
sum(t.sal) over () running_total2,
sum(t.sal) over (partition by t.deptno ) department_total2
說明:製表函式與開窗函式的關鍵不同之處:在於OVER語句上缺少一個ORDER BY子句
(4)LAG,LEAD函式:這類函式允許在結果集中向前或向後檢索值,為了避免資料的自連線,它們是非常用用的.
(5)VAR_POP,VAR_SAMP,STDEV_POPE及線性的衰減函式:計算任何未排序分割槽的統計值

2) 分析函式函式,及返回值
分析函式可取0-3個引數。引數可以是任何數字型別或是可以隱式轉換為數字型別的資料型別。Oracle根據最高數字優先級別確定函式引數,並且隱式地將需要處理的引數轉換為數字型別。函式的返回型別也為數字型別,除非此函式另有說明。

2、Analytic_Clause

[ query_partition_clause ] [ order_by_clause [ windows_clause ] ]

1)Over Analytic clause用以指明函式操作的是一個查詢結果集。也就是說分析函式是在from,where,group by,和having子句之後才開始進行計算的。因此在選擇列或order by子句中可以使用分析函式。為了過濾分析函式計算的查詢結果,可以將它作為子查詢巢狀在外部查詢中,然後在外部查詢中過濾其查詢結果。

2)使用Analytic_Clause子名時,注意如下
(1)Analytic clause中不能包含其他任何分析函式。也就是說,分析函式不能巢狀。然而可以在一個子查詢中應用分析函式,並且通過它計算另外的分析函式。
(2)使用者自定義分析函式和內建函式分析函式,都可以使用OverAnalytic_Clause。

3、PARTITION子句

partition by { value_expr [,value_expr ]… | (value_expr [,value_expr ] …)}  
說明:
按照表達式分割槽(就是分組),如果省略了分割槽子句,則全部的結果集被看作是一個單一的組
1)Partition by子句根據一個或多個valueexpr將查詢結果集分成若干組。若不使用該子句,那麼函式將查詢結果集的所有行當作一個組。
2)在分析函式中使用query_partition_clause,應該使用語法圖中上分支中的語法(不帶圓括號)。model查詢(位於model column clauses中)或被分隔的外部連線(位於outer_join_clause中)中使用該子句,應該使用語法圖中下分支中的語法(帶有圓括號)。
3) 在同一個查詢中可以使用多個分析函式,它們可以有相同或不同的partition by鍵值
4) 若被查詢的物件具有並行特性,並且分析函式中包含query_partition_clause,那麼函式的計算也是並行的。
5) value expr的有效值:包括常量,表列,非分析函式,函式表示式,或者前面這些元素的任意組合表示式。


4、ORDER BY子句

分析函式中ORDER BY的存在將新增一個預設的開窗子句(預設視窗為:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),這意味著計算中所使用的行的集合是當前分割槽中當前行和前面所有行,沒有ORDER BY時,預設的視窗是全部的分割槽 在Order by 子句後可以新增nulls last,如:order by comm desc nullslast   表示排序時忽略comm列為空的行. 

1)Order_by_clause用以指定分組中資料的排序形式。除了percentile_cont和percentile_disc之外(它們只能取唯一的鍵值)外的分析函式,分組中可以使用多個鍵值對值進行排序,每個鍵值在value expr中定義,並且被排序序列限定。

2)每個函式內可以指定多個排序表示式。當使用函式給值排名時,尤其顯得意義非凡,因為第二個表示式能夠解決按照第一個表示式排序後仍然存在相同排名的問題。

3)只要使用order_by_clause後,仍存在值相同的行,則每一行都會返回相同的結果。

4)使用Ordery_by_clause子句的限制: 
(1)分析函式中的order_by_clause必須是一個表示式(expr)。Sibling關鍵字在此處是非法的(它僅僅與層次查詢有關)。位置(position)和列別名(c_alias)也是非法的。除此之外,order_by_clause的用法與整個查詢或者子查詢中的相同。
(2)當分析函式使用range關鍵字限定視窗時,若使用的視窗是下列兩個視窗之一,那麼可以在分析函式的order_by_clause中使用多個排序健值。
① range between UNBOUNDEDPRECEDING and CURRENT ROW  <=>  range UNBOUNDED PRECEDING
② range between CURRENT ROWand UNBOUNDED FOLLOWING  <=> range UNBOUNDED FOLLOWING
注意: 若視窗範圍由range關鍵字指定的分析函式中指定的不是這兩個視窗範圍(即:range unbounded preceding與range unboundedfollowing),那麼order_by子句中僅能使用一個排序鍵值。
(3)若分析函式的視窗範圍由row關鍵字指定,order_by子句中排序鍵值的使用沒有這個限制。

5)asc | desc:指定排序順序(升序或降序),asc是預設值。

6)nulls first | nulls last:指定返回行包含空值,該值應該出現在排序序列的開始還是末尾。

7)升序排序的預設值為:nulls last,降序排序的預設值為:nulls first。

8)分析函式總是按order_by_clause對行排序。然而,分析函式中的order_by_clause只對各個分組進行排序,而不能保證查詢結果有序。要保證最後的查詢結果有序,可以使用查詢的order_by_clause。


5、WINDOWING子句


1)有些分析函式允許使用windowing clause。在上述的分析函式列表中,帶有星號(*)的函式都允許使用windowing_clause
2)用於定義分析函式將在其上操作的行的集合,Windowing子句給出了一個定義變化或固定的資料視窗的方法,分析函式將對這些資料進行操作預設的視窗是一個固定的視窗,僅僅在一組的第一行開始,一直繼續到當前行(即:range unbounded preceding),要使用視窗,必須使用ORDER BY子句。

3)row | range:這些關鍵字為每一行定義一個視窗,該視窗用於計算函式結果(物理或者邏輯的行的集合)。然後對視窗中的每一行應用分析函式。視窗在查詢結果集或者分組中從上至下移動。

4)根據2個標準可以建立視窗:資料值的範圍(邏輯偏移量--range)或與當前行的行偏移量(物理單位--rows)。

5)只有指定order_by_clause後才能指定windowing_clause。有些range子句定義的視窗範圍只能在order_by_clause中指定一個排序表示式。

6)一個帶邏輯偏移量的分析函式的返回值總是確定的。然而,除非排序表示式能產生唯一的排序,否則帶有物理偏移量的分析函式的返回值可能會產生不確定的結果。為了解決此問題,你可能不得不在order by clause中指定多個列以獲得唯一的排序。
(1)between…and:用來指定視窗的起點和終點。第一個表示式(位於and之前)定義起點,第二個表示式(位於and之後)定義終點。若不使用between而僅指定一個終點,那麼oracle認為它是起點,終點默一認為當前行。
(2)unbounded preceding:指明視窗開始於分組的第一行。它只用於指定起點而不能用於指定終點
(3)unbounded following:指明視窗結束於分組的最後一行。它只用於指定終點而不能用於指定起點
(4)current row:
① 用作起點:指定視窗開始於當前行或者當前值(依賴於是否分別指定row或者range)。在這種情況下終點不能為value_expre preceding。
② 用作終點:指定視窗結束於當前行或者當前值(依賴於是否分別指定row或者range)。在這種情況下起點不能為value_expr following。

7)range或者row中的value_expr preceding或者value_expr following:
(1)若value_expr  FOLLOWING是起點,那麼終點必須為:value_exprFOLLOWING。
(2)若value_expr  PRECEDING是終點,那麼起點必須是:value_exprPRECEDING。
(3)若要定義一個數字格式的時間間隔的邏輯視窗,那麼可能需要用到轉換函式(numtoyminterval與numtodsinterval)

8)若windowing_clause由range指定:
(1)value_expr是一個邏輯偏移量。它必須是常量,或者值為正數值的表示式,或者時間間隔文字常量。
(2)只能在order_by_clause中指定一個表示式。
(3)若value_expr求值為一個數字值,那麼order_by_expr必須為數字或者date型別。
(4)若value_expr求值為一個間隔值,那麼order_by_expr必須是一個date型別。
(5)若完全忽略windowing_clause,那麼預設值為: range between unbounded preceding and current row。
注意:r
ange 5 preceding:將產生一個滑動視窗,它在組中擁有當前行以及前5行的集合;
RANGE視窗僅對NUMBERS和DATES起作用,因為不可能從VARCHAR2中增加或減去N個單元,另外的限制是ORDER BY中只能有一列,因而範圍實際上是一維的,不能在N維空間中
例:avg(t.sal) over(order by t.hiredate asc range 100preceding) 統計前100天平均工資


8)若windowing_clause由rows指定:
(1)value_expr是一個物理偏移量,它必須是一個常量或者表示式,並且表示式的值必須是正數值
(2)若value_expr是起點的一部分,那麼它必須在終點之前對行求值。
(3)利用ROW分割槽,就沒有RANGE分割槽那樣的限制了,資料可以是任何型別,且ORDER BY 可以包括很多列

9)常用的Specifying視窗
(1)UNBOUNDED PRECEDING:這個視窗從當前分割槽的每一行開始,並結束於正在處理的當前行
(2)CURRENT ROW:該視窗從當前行開始(並結束)
(3)Numeric Expression PRECEDING:對該視窗從當前行之前的數字表達式(Numeric Expression)的行開始,對RANGE來說,從從行序值小於數字表達式的當前行的值開始.
(4)Numeric Expression FOLLOWING:該視窗在當前行Numeric Expression行之後的行終止(或開始),且從行序值大於當前行NumericExpression行的範圍開始(或終止)
例如:range between 100 preceding and 100 following:當前行100前,當前後100後
注意:分析函式允許你對一個數據集進排序和篩選,這是SQL從來不能實現的.除了最後的Order by子句之外,分析函式是在查詢中執行的最後的操作集,這樣的話,就不能直接在謂詞中使用分析函式,即不能在上面使用where或having子句!!