.Net程序員學用Oracle系列(22):分析函數(OVER)


分析函數用於計算一組行的聚合值,由分析函數語法定義的行集叫做窗口,窗口的大小由物理行數或邏輯間隔決定。每一行上的滑動窗口都是已定義的,窗口決定了對某一行而言進行計算的行的范圍。從查詢結果和查詢語法來看,分析函數與聚合函數主要有 3 點不同:

  • 1、聚合函數每組只返回一條記錄,而分析函數每組可返回多條記錄。
  • 2、在單個查詢中,多個聚合函數只能作用於同一個分組,而不同分析函數可作用於不同分組。
  • 3、在分組查詢中,查詢列表只能出現聚合函數或 GROUP BY 子句中出現過的字段或常量或表達式,而分析函數沒有這些限制。

1、函數語法

我理解的分析函數無非也就是由一或多個普通的函數或子句按照一定的規則構成的復雜數據分析函數。換言之,分析函數內部有些函數或子句的語法規則之前已經講述過了,這里將不再贅述,本節將着重講述分析函數所特有的一些函數或子句的語法。

1.1、語法概述

有很多網站都把分析函數稱之為窗口函數,又稱 OVER 為開窗函數,還有些似是而非的概念我本人也不甚了解。我特地查閱過 《Oracle Database SQL Reference 10g Release 2》Analytic Functions,語法如下:

analytic_function([arguments]) OVER([analytic_clause])

參數說明:

  • analytic_function:分析函數的名稱。Oracle 10g R2 中內置了 30 個分析函數。
  • arguments:分析函數的參數。內置的分析函數一般帶 0~3 個參數,參數可以是任何數字類型或是可以隱式轉換為數字類型的數據類型。
  • OVER:用來標識函數是個分析函數。對於即可作為聚合函數又可作為分析函數的函數,Oracle 無法識別,必須用 OVER 來標識此函數為分析函數。但並不是說只可作為分析函數的函數就無需標識,是分析函數就必須用 OVER 關鍵字來標識。另外 OVER 后面的一對小括號也是必須的,即便括號中什么都不包含。
  • analytic_clause:用來確定分析規則。語法是:[query_partition_clause][order_by_clause[windowing_clause]],語法中的 3 個子句都是可選的,但 windowing_clause 必須依賴於 order_by_clause 而存在。
    • query_partition_clause:分組子句,用於確定窗口,與 GROUP BY 語句的語法類似。
    • order_by_clause:排序子句,用於確定窗口規則,與 ORDER BY 語句的語法類似。
    • windowing_clause:窗口范圍子句,用於確定分組中當前的計算范圍。

1.2、窗口詳解

《Oracle Database SQL Reference 10g Release 2》 中給出 windowing_clause 語法示意圖如下:
windowing_clause

  • ROWS:用於指定窗口由物理行構成,即符合指定的數據行的范圍。
  • RANGE:用於指定窗口由邏輯偏移量構成,即符合指定的邏輯條件的范圍。
  • BETWEEN...AND:用於指定窗口的起始點和終結點。
  • UNBOUNDED PRECEDING:用於指明窗口開始於分組的第一行。
  • CURRENT ROW:作為起始點,指明窗口開始於當前行或當前行的值;作為終結點,指明窗口結束於當前行或當前行的值。
  • UNBOUNDED FOLLOWING:用於指明窗口結束於分組的最后一行。
  • value_expr:物理或邏輯偏移量的表達式。

無論是窗口大小是由物理行數(ROWS)確定,還是由邏輯間隔(RANGE)確定,在分組中窗口總是從上往下滑動。窗口范圍可以由 BETWEEN...AND 限定,也可以不用 BETWEEN...AND,不用則表示窗口到當前行或值結束。

1.2.1、ROWS 窗口

ROWS 窗口是由分組排序后分組中若干連續的行所構成的窗口。在 ROWS 窗口中 value_expr 是物理偏移量,它必須是常量或值為非負數的表達式。合法的 ROWS 窗口范圍定義共有 16 種,列舉如下:

1、窗口開始於分組第一行,結束於分組最后一行。

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

2、窗口開始於分組第一行,結束於當前行。

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
ROWS UNBOUNDED PRECEDING

3、窗口開始於分組第一行,結束於當前行的前 value_expr 行。

ROWS BETWEEN UNBOUNDED PRECEDING AND value_expr PRECEDING

4、窗口開始於分組第一行,結束於當前行的后 value_expr 行。

ROWS BETWEEN UNBOUNDED PRECEDING AND value_expr FOLLOWING

5、窗口開始於當前行,結束於分組最后一行。

ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

6、窗口開始於當前行,結束於當前行。

ROWS BETWEEN CURRENT ROW AND CURRENT ROW
ROWS CURRENT ROW

7、窗口開始於當前行,結束於當前行的前 value_expr 行。

ROWS BETWEEN CURRENT ROW AND value_expr PRECEDING

8、窗口開始於當前行,結束於當前行的后 value_expr 行。

ROWS BETWEEN CURRENT ROW AND value_expr FOLLOWING

9、窗口開始於當前行的前 value_expr 行,結束於當前行。

ROWS BETWEEN value_expr PRECEDING AND CURRENT ROW
ROWS value_expr PRECEDING

10、窗口開始於當前行的前 value_expr1 行,結束於當前行的前 value_expr2 行。前提是要滿足 value_expr1 >= value_expr2。

ROWS BETWEEN value_expr1 PRECEDING AND value_expr2 PRECEDING

11、窗口開始於當前行的前 value_expr1 行,結束於當前行的后 value_expr2 行。

ROWS BETWEEN value_expr1 PRECEDING AND value_expr2 FOLLOWING

12、窗口開始於當前行的后 value_expr 行,結束於分組最后一行。

ROWS BETWEEN value_expr FOLLOWING AND UNBOUNDED FOLLOWING

13、窗口開始於當前行的后 value_expr1 行,結束於當前行的后 value_expr2 行。前提是要滿足 value_expr1 <= value_expr2。

ROWS BETWEEN value_expr1 FOLLOWING AND value_expr2 FOLLOWING

1.2.2、RANGE 窗口

RANGE 窗口是由分組排序后分組中滿足指定邏輯條件的行所構成的窗口。在 RANGE 窗口中 value_expr 為邏輯偏移量,它必須是常量或值為非負數的表達式或間隔值。當 value_expr 值是一個數字時,排序字段必須是數字或日期類型;當 value_expr 值是一個間隔值時,排序字段必須是一個日期類型。合法的 RANGE 窗口范圍定義也有 16 種,列舉如下:

1、升序排序時,表達式介於第一行的值和最后一行的值之間;降序排序時,表達式介於最后一行的值和第一行的值之間。

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

2、升序排序時,表達式介於第一行的值和當前行的值之間;降序排序時,表達式介於當前行的值和第一行的值之間。若不指定窗口,則默認為該窗口

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
RANGE UNBOUNDED PRECEDING

3、升序排序時,表達式介於第一行的值和當前行的值 -value_expr 之間;降序排序時,表達式介於當前行的值 -value_expr 和第一行的值之間。

RANGE BETWEEN UNBOUNDED PRECEDING AND value_expr PRECEDING

4、升序排序時,表達式介於第一行的值和當前行的值 +value_expr 之間;降序排序時,表達式介於當前行的值 +value_expr 和第一行的值之間。

RANGE BETWEEN UNBOUNDED PRECEDING AND value_expr FOLLOWING

5、升序排序時,表達式介於當前行的值和最后一行的值之間;降序排序時,表達式介於最后一行的值和當前行的值之間。

RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

6、表達式等於當前行的值。

RANGE BETWEEN CURRENT ROW AND CURRENT ROW
RANGE CURRENT ROW

7、表達式介於當前行的值和當前行的值 +value_expr 之間。

RANGE BETWEEN CURRENT ROW AND value_expr FOLLOWING

8、表達式介於當前行的值 -value_expr 和最后一行的值之間。

RANGE BETWEEN value_expr PRECEDING AND UNBOUNDED FOLLOWING

9、表達式介於當前行的值 -value_expr 和當前行的值之間。

RANGE BETWEEN value_expr PRECEDING AND CURRENT ROW
RANGE value_expr PRECEDING

10、表達式介於當前行的值 -value_expr1 和當前行的值 -value_expr2 之間。前提是要滿足 value_expr1 >= value_expr2。

RANGE BETWEEN value_expr1 PRECEDING AND value_expr2 PRECEDING

11、表達式介於當前行的值 -value_expr1 和當前行的值 +value_expr2 之間。

RANGE BETWEEN value_expr1 PRECEDING AND value_expr2 FOLLOWING

12、升序排序時,表達式介於當前行的值 +value_expr 和最后一行的值之間;降序排序時,表達式介於最后一行的值和當前行的值 +value_expr 之間。

RANGE BETWEEN value_expr FOLLOWING AND UNBOUNDED FOLLOWING

13、表達式介於當前行的值 +value_expr1 和當前行的值 +value_expr2 之間。前提是要滿足 value_expr1 <= value_expr2。

RANGE BETWEEN value_expr1 FOLLOWING AND value_expr2 FOLLOWING

2、函數用法

Oracle 10g R2 中內置的分析函數有 38 個,本節按函數用途將其分為 4 類,分別是:普通統計函數、數據排序函數、數據分布函數及統計分析函數,並逐一給出函數釋義和用法示例。

2.1、普通統計類函數

  • MAX:對組內的數據窗口中的字段或表達式求最大值。
  • MIN:對組內的數據窗口中的字段或表達式求最小值。
  • AVG:對組內的數據窗口中的字段或表達式求平均值。
  • SUM:對組內的數據窗口中的字段或表達式求合計值。
  • COUNT:對組內的數據窗口中的數據行進行累計計數。

示例 1:

SELECT t.staff_name,t.dept_code,t.base_salary,t.post_salary,
  MAX(t.post_salary) OVER(PARTITION BY t.dept_code) max_salary,  -- 部門最高崗位工資
  MIN(t.post_salary) OVER(PARTITION BY t.dept_code) min_salary,  -- 部門最低崗位工資
  AVG(t.post_salary) OVER(PARTITION BY t.dept_code) avg_salary,  -- 部門平均崗位工資
  SUM(t.post_salary) OVER(PARTITION BY t.dept_code) sum_salary,  -- 部門崗位工資之和
  COUNT(t.post_salary) OVER(PARTITION BY t.dept_code) cnt_salary -- 部門工資份數
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

示例 2:

SELECT t.staff_name,t.dept_code,t.base_salary,t.post_salary,
  -- 部門內截至當前行的最高崗位工資
  MAX(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary ROWS UNBOUNDED PRECEDING) max_salary,
  -- 部門內當前行至最后一行的最低崗位工資
  MIN(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary ROWS CURRENT ROW) min_salary,
  -- 部門內第一行至前一行的平均崗位工資
  AVG(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) avg_salary,
  -- 部門內第一行至后一行的崗位工資之和
  SUM(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) sum_salary,
  -- 部門內截至當前行的工資份數
  COUNT(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary ROWS UNBOUNDED PRECEDING) cnt_salary
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

2.2、數據排序類函數

  • RANK():根據 ORDER BY 的排序結果,計算組間相對位置,可能跳號。組內數據按 ORDER BY 子句排序,每一行都會得到一個序號,從而形成一個序列,該序列從 1 開始,往后 ORDER BY 表達式的值每發生一次變化,該序列也隨之加 1。值相同的行將得到相同的序號(NULL 被認為是相等的),后面行的序號將發生跳躍。如前兩行的序號為 1,則沒有序號 2,第 3 行將得到序號 3。
  • DENSE_RANK():根據 ORDER BY 的排序結果,計算組間相對位置,不會跳號。DENSE_RANK 與 RANK 類似,也會得到一個首項為 1、公差為 1 的等差序列,值相同的行序號也相同(也認為 NULL 是相等的),但序號不會跳躍。如前兩行的序號為 1,第 3 行將得到序號 2。
  • FIRST_VALUE(expression):返回組內數據窗口的第一個值。
  • LAST_VALUE(expression):返回組內數據窗口的最后一個值。
  • LAG(expression [, offset [, default] ]):可以訪問結果集中當前行之前的行而不用進行自連接,這樣就可以從組中與當前行一起選取當前行之前的行。offset 是一個正整數,默認值為 1,若不指定 offset,或 offset 的值超出窗口范圍,就啟用默認值。
  • LEAD(expression [, offset [, default] ]):與 LAG 相反,LEAD 可以訪問結果集中當前行之后的行而不用進行自連接,這樣就可以從組中與當前行一起選取當前行之后的行。offset 是一個正整數,默認值為 1,若不指定 offset,或 offset 的值超出窗口范圍,就啟用默認值。
  • ROW_NUMBER:返回有序組中一行的偏移量,按特定的排序分配行號。
  • FIRST:從緊湊排序后的結果集中篩選出排在最前面的一個值的行(可能是多行,因為值可能相等)。
  • LAST:從緊湊排序后的結果集中篩選出排在最后面的一個值的行(可能是多行,因為值可能相等)。

示例 1:

SELECT t.dept_code,t.staff_name,t.post_salary,
  RANK() OVER(ORDER BY t.dept_code,t.post_salary) rank,
  DENSE_RANK() OVER(ORDER BY t.dept_code,t.post_salary) dense_rank,
  FIRST_VALUE(t.post_salary) OVER(ORDER BY t.dept_code,t.post_salary) fist_value,
  LAST_VALUE(t.post_salary) OVER(ORDER BY t.dept_code,t.post_salary) last_value,
  LAG(t.post_salary,1,0) OVER(ORDER BY t.dept_code,t.post_salary) lag_value,
  LEAD(t.post_salary,1,0) OVER(ORDER BY t.dept_code,t.post_salary) lead_value,
  ROW_NUMBER() OVER(ORDER BY t.dept_code,t.post_salary) row_number
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

示例 2:

SELECT t.dept_code,t.staff_name,t.birthday,t.post_salary,
  RANK() OVER(PARTITION BY t.dept_code ORDER BY t.post_salary) rank,
  DENSE_RANK() OVER(PARTITION BY t.dept_code ORDER BY t.post_salary) dense_rank,
  FIRST_VALUE(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary) fist_value,
  LAST_VALUE(t.post_salary) OVER(PARTITION BY t.dept_code ORDER BY t.post_salary) last_value,
  LAG(t.post_salary,1,0) OVER(PARTITION BY t.dept_code ORDER BY t.dept_code,t.post_salary) lag_value,
  LEAD(t.post_salary,1,0) OVER(PARTITION BY t.dept_code ORDER BY t.dept_code,t.post_salary) lead_value,
  ROW_NUMBER() OVER(PARTITION BY t.dept_code ORDER BY t.dept_code,t.post_salary) row_number
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

示例 3:

SELECT t.staff_name,t.gender,t.dept_code,t.post_salary,
  MIN(t.post_salary) KEEP(DENSE_RANK FIRST ORDER BY t.dept_code) OVER(PARTITION BY t.gender) first_value1,
  MAX(t.post_salary) KEEP(DENSE_RANK FIRST ORDER BY t.dept_code) OVER(PARTITION BY t.gender) first_value2,
  MIN(t.post_salary) KEEP(DENSE_RANK LAST ORDER BY t.dept_code) OVER(PARTITION BY t.gender) last_value1,
  MAX(t.post_salary) KEEP(DENSE_RANK LAST ORDER BY t.dept_code) OVER(PARTITION BY t.gender) last_value2
FROM demo.t_staff t 
ORDER BY t.gender,t.dept_code;

2.3、數據分布類函數

  • RATIO_TO_REPORT(expr):計算當前行的值與組中所有行的值之和的比率。
  • NTILE(expr):將一組有序的數據集分為若干桶,並為每一行分配相應的桶編號。expr 必須是能被解析成正整數的值或表達式,如果帶小數,小數部分將被截取。桶編號從 1 開始到 TRUNC(expr),每桶的數據行數最多相差 1。如果行數不能被桶數整除,那么靠前的桶將優先被填充,靠后的桶則會少一行數據。例如 expr=3,行數=16,則桶編號為 1 的有 6 行,桶編號為 2 或 3 的有 5 行。
  • CUME_DIST():計算一組值的累計分布,並返回大於 0、小於或等於 1 的數,該數表示該行在組中的相對位置,值相等的相鄰行會得到相同的累計分布值。
  • PERCENT_RANK():與 CUME_DIST 函數類似,每行的值等於該行的行號先減去 1,再除以組中總行數減去 1,因此返回值總是大於或等於 0、小於或等於 1。
  • PERCENTILE_DISC(expr):返回一個與分布百分比想對應的數值,分布百分比的計算方法參見 CUME_DIST 函數(計算時 NULL 會被忽略)。
  • PERCENTILE_CONT(expr):返回一個與分布百分比想對應的數值,分布百分比的計算方法參見 PERCENT_RANK 函數(計算時 NULL 會被忽略)。
  • REGR_ (Linear Regression) Functions:這些線性回歸函數適合最小二乘法回歸線,共有 9 個不同的回歸函數。
    • REGR_SLOPE:返回斜率。相當於 COVAR_POP(expr1, expr2) / VAR_POP(expr2)。
    • REGR_INTERCEPT:返回回歸線的 y 截距。相當於 AVG(expr1) - REGR_SLOPE(expr1, expr2) * AVG(expr2)。
    • REGR_COUNT:返回用於填充回歸線的非空數字對的數目。
    • REGR_R2:返回回歸線的決定系數。如果 VAR_POP(expr2) = 0,則為 NULL;如果 VAR_POP(expr1) = 0 且 VAR_POP(expr2) != 0,則為 1;如果 VAR_POP(expr1) > 0 且 VAR_POP(expr2) != 0,則為 POWER(CORR(expr1,expr),2)。
    • REGR_AVGX:計算回歸線自變量 (expr2) 的平均值。在去掉空對 (expr1,expr2) 后,相當於 AVG(expr2)。
    • REGR_AVGY:計算回歸線應變量 (expr1) 的平均值。在去掉空對 (expr1,expr2) 后,相當於 AVG(expr1)。
    • REGR_SXX:在去掉空對 (expr1,expr2) 后,相當於 REGR_COUNT(expr1, expr2) * VAR_POP(expr2)。
    • REGR_SYY:在去掉空對 (expr1,expr2) 后,相當於 REGR_COUNT(expr1, expr2) * VAR_POP(expr1)。
    • REGR_SXY:在去掉空對 (expr1,expr2) 后,相當於 REGR_COUNT(expr1, expr2) * COVAR_POP(expr1, expr2)。

示例 1:

SELECT t.staff_name,t.dept_code,t.post_salary,
  RATIO_TO_REPORT(t.post_salary) OVER() ratio_to_report,
  NTILE(3) OVER(ORDER BY t.dept_code,t.post_salary) ntile,
  CUME_DIST() OVER(ORDER BY t.dept_code,t.post_salary) cume_dist,
  PERCENT_RANK() OVER(ORDER BY t.dept_code,t.post_salary) percent_rank
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

示例 2:

SELECT t.staff_name,t.dept_code,t.post_salary,
  RATIO_TO_REPORT(t.post_salary) OVER(PARTITION BY t.dept_code) ratio_to_report,
  NTILE(3) OVER(PARTITION BY t.dept_code ORDER BY t.dept_code,t.post_salary) ntile,
  CUME_DIST() OVER(PARTITION BY t.dept_code ORDER BY t.dept_code,t.post_salary) cume_dist,
  PERCENT_RANK() OVER(ORDER BY t.dept_code,t.post_salary) percent_rank,
  PERCENTILE_DISC(0.5) WITHIN GROUP(ORDER BY t.post_salary) OVER(PARTITION BY t.dept_code) percentile_disc,
  PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY t.post_salary) OVER(PARTITION BY t.dept_code) percentile_cont
FROM demo.t_staff t 
ORDER BY t.dept_code,t.post_salary;

2.4、統計分析類函數

  • CORR(expr1, expr2):返回一對數的相關系數。相當於COVAR_POP(expr1, expr2) / (STDDEV_POP(expr1) * STDDEV_POP(expr2))
  • COVAR_POP(expr1, expr2):返回一對數總體協方差。相當於(SUM(expr1 * expr2) - SUM(expr2) * SUM(expr1) / n) / n
  • COVAR_SAMP(expr1, expr2):返回一對數的樣本協方差。相當於(SUM(expr1 * expr2) - SUM(expr1) * SUM(expr2) / n) / (n-1)
  • STDDEV([DISTINCT | ALL] expr):計算當前行關於組的標准偏離。
  • STDDEV_POP(expr):計算總體標准差,並返回總體方差的平方根。與 VAR_POP 函數的平方根相同。
  • STDDEV_SAMP(expr):計算累積樣本標准偏差,並返回樣本方差的平方根。與 VAR_SAMP 函數的平方根相同。
  • VAR_POP(expr):返回非空(即忽略 NULL)數對的總體方差。
  • VAR_SAMP(expr):返回非空(即忽略 NULL)數對的樣本方差。
  • VARIANCE([ DISTINCT | ALL ] expr):如果 expr = 1,則返回 0;如果 expr > 1,則返回 VAR_SAMP。

3、補充案例

案例 1,逐行累加(在實現諸如沖銷、抵扣之類的功能時,該案例的寫法非常有用):

WITH t AS(
  SELECT 1 val FROM DUAL UNION ALL
  SELECT 3 FROM DUAL UNION ALL
  SELECT 5 FROM DUAL UNION ALL
  SELECT 7 FROM DUAL UNION ALL
  SELECT 9 FROM DUAL
)
SELECT t.val,
  SUM(t.val) OVER(ORDER BY ROWNUM ROWS UNBOUNDED PRECEDING) cur_sum_val,
  SUM(t.val) OVER(ORDER BY ROWNUM ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) pre_sum_val 
FROM t;

結果:

       VAL CUR_SUM_VAL PRE_SUM_VAL
---------- ----------- -----------
         1           1 
         3           4           1
         5           9           4
         7          16           9
         9          25          16

案例 2,取 A、B 兩級中數值最小的行(在實現階段性進度計划統計分析報表時,該案例的寫法非常有用):

WITH t AS(
  SELECT 'A' grade, 1 val FROM DUAL UNION ALL
  SELECT 'A',3 FROM DUAL UNION ALL
  SELECT 'A',5 FROM DUAL UNION ALL
  SELECT 'B',7 FROM DUAL UNION ALL
  SELECT 'B',9 FROM DUAL
)
SELECT t2.grade,t2.val FROM(
  SELECT t.grade,t.val,RANK() OVER(PARTITION BY t.grade ORDER BY val) rank FROM t
) t2 WHERE t2.rank=1;

結果:

GRADE        VAL
----- ----------
A              1
B              7

案例 3,查出各部門最年長和最年輕的員工信息:

SELECT DISTINCT t1.dept_code,t2.enum_name dept_name,
  FIRST_VALUE(t1.staff_name) OVER(PARTITION BY t1.dept_code ORDER BY t1.birthday) max_older_name,
  FIRST_VALUE(t1.staff_name) OVER(PARTITION BY t1.dept_code ORDER BY t1.birthday DESC) min_young_name
FROM demo.t_staff t1
LEFT JOIN demo.t_field_enum t2 ON t2.field_code='DEPT' AND t1.dept_code=t2.enum_code
ORDER BY t1.dept_code; -- 注意:此處一旦用了 DISTINCT,ORDER BY 列表中的字段就必須是 SELECT 列表中出現過的

結果:

DEPT_CODE                DEPT_NAME                    MAX_OLDER_NAME               MIN_YOUNG_NAME
------------------------ ---------------------------- ---------------------------- ---------------------------
010101                   研發一部                     小明                         王二
010102                   研發二部                     小薩                         小林
010103                   研發三部                     韓三                         小玲
010104                   測試部                       小梅                         小燕
010201                   實施一部                     小軍                         小紅
010202                   實施二部                     小飛                         小飛

總結

嚴格來說本文應該算是分析函數的入門篇,因為只講述了分析函數的語法和簡單用法。盡管窗口規則比較多,但只要稍作分析,就會發現其實並不復雜,重點是要能結合實際情況靈活運用。最好的參考就是補充案例一,我本人當初也是在網上看到一條類似補充案例一中的 SQL 語句后才開始我的分析函數之旅的!巧的是沒過多久公司財務要求在報銷流程中增加智能沖銷功能,恰好用上!

本文列出了 Oracle 10g 中的所有分析函數。其中普通統計類函數和數據排序類函數我用過一些,因為除了解釋函數用途還給出了一些示例。但數據分布類函數和統計分析類函數大多只給出了簡單的釋義,主要是因為在日常開發中極少用到,而且大部分我也從沒用過。如果你想進一步了解的話請參考官方手冊:Analytic Functions

本文鏈接http://www.cnblogs.com/hanzongze/p/oracle-over.html
版權聲明:本文為博客園博主 韓宗澤 原創,作者保留署名權!歡迎通過轉載、演繹或其它傳播方式來使用本文,但必須在明顯位置給出作者署名和本文鏈接!本人初寫博客,水平有限,若有不當之處,敬請批評指正,謝謝!


免責聲明!

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



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