[Oracle] 分析函式(2)- 開窗(WINDOWING)
阿新 • • 發佈:2018-12-30
SELECT emp_id,ename,dept_id,hire_date,sal, -- 以下均為首先按dept_id進行分組,其次按照hire_date進行排序,且所有統計不能跨越其所在分割槽,故不再重複 -- 視窗範圍為該分割槽的第一行到該分割槽的最後一行,與sum_sal_part等同 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) sum_1_to_last, -- 視窗範圍為該分割槽的第一行到本行,與sum_sal_part_order等同 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) sum_1_to_cur, -- 視窗範圍為該分割槽的第一行到本行前一行,統計的是第一行到本行前一行薪資的累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1/*value_expr*/ PRECEDING) sum_1_to_curbef1, -- 視窗範圍為該分割槽的第一行到本行後一行,統計的是第一行到本行後一行薪資的累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) sum_1_to_curaft1 FROM emp order by dept_id,hire_date; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM_1_TO_LAST SUM_1_TO_CUR SUM_1_TO_CURBEF1 SUM_1_TO_CURAFT1 ------ ----- ------- -------------- ----- ------------- ------------ ---------------- ---------------- 100 Stev 10 01-1月 -90 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 10000 2000 10000 解說SUM1_TO_CUR(dept_id=50部分) 解說SUM1_TO_CURaft1 (dept_id=50部分) 102 Mike 20 13-1月 -93 8000 10000 10000 2000 10000 122 Rich 50 01-5月 -95 3000 19000 3000 4000 ---從第1行hiredates順序到當前行(也就是到第1行),多少?該3000就3000 ---從第1行hiredates順序到當前行後1行(也就是到第2行),多少?300+1000 120 John 50 18-7月 -96 1000 19000 4000 3000 8000 ---比第1行hiredates順序到當前行(也就是到第2行),多少?3000+1000=4000 ---比第1行hiredates順序到當前行後1行(也就是到第3行),多少?3000+1000+4000 121 Joy 50 10-4月 -97 4000 19000 8000 4000 13000 ---比第1行hiredates順序到當前行(也就是到第3行),多少?3000+1000+4000 ---比第1行hiredates順序到當前行後1行(也就是到第4行),多少?3000+1000+4000+5000 123 Kate 50 10-10月-97 5000 19000 13000 8000 19000 ---比第1行hiredates順序到當前行(也就是到第4行),多少?3000+1000+4000+5000 ---比第1行hiredates順序到當前行後1行(也就是到第5行),多少?3000+1000+4000+5000+6000 124 Jess 50 16-11月-99 6000 19000 19000 13000 19000 ---比第1行hiredates順序到當前行(也就是到第4行),多少?3000+1000+4000+5000+6000 ---比第1行hiredates順序到當前行後1行(也就是到第6行,第6行沒記錄了,那結果和上一次一樣) SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為本行和該分割槽的最後一行,統計的是大於等於本記錄hire_date之後的所有薪資 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) sum_cur_to_last, -- 視窗範圍只是本行,所以與本行薪資一樣 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN CURRENT ROW AND CURRENT ROW) sum_cur, -- 視窗範圍為本行到本行的後一行,統計的本行到後一行的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN CURRENT ROW AND 1/*value_expr*/ FOLLOWING) sum_cur_to_aft1, -- 視窗範圍為本行和本行的後一行,統計的本行前一行到本分割槽最後一行的薪資累計,如本行為分割槽首行,則直接從本行開始算起 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 1/*value_expr*/ PRECEDING AND UNBOUNDED FOLLOWING) sum_curbef1_to_last FROM emp order by dept_id,hire_date; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM_CUR_TO_LAST SUM_CUR SUM_CUR_TO_AFT1 SUM_CURBEF1_TO_LAST ------ ----- ------- -------------- ----- --------------- ---------- --------------- ------------------- 100 Stev 10 01-1月 -90 7000 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 10000 2000 10000 10000 解說SUM_CUR_TO_AFT1(dept_id=50部分) 102 Mike 20 13-1月 -93 8000 8000 8000 8000 10000 122 Rich 50 01-5月 -95 3000 19000 3000 4000 19000 ---從第1行hiredates順序到當前行(也就是第1行)到下1行,多少?3000+1000 120 John 50 18-7月 -96 1000 16000 1000 5000 19000 ---比第1行hiredates順序到當前行(也就是第2行)到下1行,多少?1000+4000 121 Joy 50 10-4月 -97 4000 15000 4000 9000 16000 ---比第1行hiredates順序到當前行(也就是第3行)到下1行,多少?4000+5000 123 Kate 50 10-10月-97 5000 11000 5000 11000 15000 ---比第1行hiredates順序到當前行(也就是第4行)到下1行,多少?5000+6000 124 Jess 50 16-11月-99 6000 6000 6000 6000 11000 ---比第1行hiredates順序到當前行(也就是第5行)到下1行,多少?下行沒了,那就是6000 SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為該分割槽的本行和本行前一行,統計的是當本行和本行的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 1/*value_expr*/ PRECEDING AND CURRENT ROW) sum_cur_to_bef1, -- 視窗範圍為該分割槽的本行前value_expr1到本行前value_expr2的累計,本例為本行前2行和前1行的累計,強調value_expr1>=value_expr2 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 2/*value_expr1*/ PRECEDING AND 1/*value_expr2*/ PRECEDING) sum_curbef2_to_bef1, -- 視窗範圍為該分割槽的本行前value_expr1到本行後value_expr2的累計,本例為本行前1行到後2行的累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 1/*value_expr1*/ PRECEDING AND 2/*value_expr2*/ FOLLOWING) sum_curbef1_to_aft2, -- 視窗範圍為該分割槽的本行後一行和本區最後一行,統計的是本行後一行和本區最後一行的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 1/*value_expr*/ FOLLOWING AND UNBOUNDED FOLLOWING) sum_curaft1_to_last FROM emp order by dept_id,hire_date; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM_CUR_TO_BEF1 SUM_CURBEF2_TO_BEF1 SUM_CURBEF1_TO_AFT2 SUM_CURAFT1_TO_LAST ------ ----- ------- -------------- ----- --------------- ------------------- ------------------- ------------------- 100 Stev 10 01-1月 -90 7000 7000 7000 101 Tom 20 21-9月 -89 2000 2000 10000 8000 解說SUM_CURBEF2_TO_BEF1(dept_id=50部分) 102 Mike 20 13-1月 -93 8000 10000 2000 10000 122 Rich 50 01-5月 -95 3000 3000 8000 16000 ---從第1行hiredate順序到當前行(也就是第1行),往前2位,沒數字,往前1位,依然沒數字! 120 John 50 18-7月 -96 1000 4000 3000 13000 15000 ---比第1行hiredate順序到當前行(也就是第2行)往前2位,沒數字,往前1位,3000 121 Joy 50 10-4月 -97 4000 5000 4000 16000 11000 ---比第1行hiredate順序到當前行(也就是第3行)往前2位,3000,往前1位,1000,是3000+1000 123 Kate 50 10-10月-97 5000 9000 5000 15000 6000 ---比第1行hiredate順序到當前行(也就是第4行)往前2位,1000,往前1位,4000,是1000+4000 124 Jess 50 16-11月-99 6000 11000 9000 11000 ---比第1行hiredate順序到當前行(也就是第5行)往前2位,4000,往前1位,5000,是4000+5000 SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為該分割槽的本行後value_expr1到本行後value_expr2的累計,本例為本行後1行和後2行的累計,強調value_expr1<=value_expr2 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS BETWEEN 1/*value_expr1*/ FOLLOWING AND 2/*value_expr2*/ FOLLOWING) sum_curaft1_to_after2, -- 視窗範圍為該分割槽的第一行,結束行預設為本行,與之前出現的sum_sal_part_order,sum_1_to_cur等同 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS UNBOUNDED PRECEDING) sum_1_to_cur, -- 視窗範圍僅為當前行,所以與本行薪資一樣,與之前出現的sum_cur一樣 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS CURRENT ROW) sum_cur, -- 視窗範圍為該分割槽的本行和本行前一行,統計的是本行前一行和本行的薪資累計,與之前出現的sum_cur一樣 SUM(sal) OVER (PARTITION BY dept_id ORDER BY hire_date ROWS 1/*value_expr*/ PRECEDING) sum_cur_to_bef1 FROM emp order by dept_id,hire_date; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM_CURAFT1_TO_AFTER2 SUM_1_TO_CUR SUM_CUR SUM_CUR_TO_BEF1 ------ ----- ------- -------------- ----- --------------------- ------------ ---------- --------------- 100 Stev 10 01-1月 -90 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 8000 2000 2000 2000 解說SUM_CURAFTER1_TO_AFTER1(dept_id=50部分) 102 Mike 20 13-1月 -93 8000 10000 8000 10000 122 Rich 50 01-5月 -95 3000 5000 3000 3000 3000 ---從第1行hiredate順序到當前行(也就是第1行),往後1位,1000,後2位,4000,是1000+4000 120 John 50 18-7月 -96 1000 9000 4000 1000 4000 ---從第1行hiredate順序到當前行(也就是第2行),往後1位,4000,後2位,5000,是4000+5000 121 Joy 50 10-4月 -97 4000 11000 8000 4000 5000 ---從第1行hiredate順序到當前行(也就是第3行),往後1位,5000,後2位,6000,是5000+6000 123 Kate 50 10-10月-97 5000 6000 13000 5000 9000 ---從第1行hiredate順序到當前行(也就是第4行),往後1位,6000,後2位,沒了 124 Jess 50 16-11月-99 6000 19000 6000 11000 ---從第1行hiredate順序到當前行(也就是第5行),往後1位,沒了,後2位,更沒了!
RANGE視窗
RANGE的例子:range 是關鍵字,指定視窗由邏輯偏移量構成,即符合指定的邏輯條件的範圍。 between…and是關鍵字,用來指定視窗的起始點和終結點; Unbounded preceding指明視窗開始於分組的第一行; Current row,作為起始點,指明視窗開始於當前行或當前值;作為終結點,指明視窗結束於當前行或當前值; Unbounded following指明視窗結束於分組的最後一行; Value_expr為物理或邏輯偏移量表達式。 RANGE視窗,相當於給order_by_clause中的expr加一個where限定條件,分組中滿足條件 (當order by expr asc時,where expr between a and b 當order by expr desc時 where expr between b and a)的所有行構成一個邏輯視窗。 其中a由分組中第ra行的值計算而來,b由分組中第rb行的值計算而來,且ra<=rb。 根據range中是否包含unbounded,可以分為兩類,含unbounded range視窗,和不含unbounded range視窗。 對於前者,有ra<=rb。當order by expr asc時,a<=b,須使用where expr between a and b;當order by expr desc時,a>b,須使用where expr between b and a。 對於後者,有ra=rb。總有a<=b,使用where expr between a and b。 對於在order_by_clause中可以使用多個expr的視窗: Range between unbounded preceding and current row Range between current row and unbounded following 當它們使用多個expr排序時(注意不是一個)分別等價於: Rows between unbounded preceding and current row Rows between current row and unbounded following 假設分組第一行的值為first_value,最後一行的值為last_value。當前行的值為current_value。 1)range between unbounded preceding and unbounded following 按升序排序的時候,表示式介於第一個值和最後一個值之間,或者 按降序排序的時候,表示式介於最後一個值和第一個值之間 2)range [between] unbounded preceding [and current row] 表示式介於第一個值與當前行的值之間,或者 表示式介於當前行的值和第一個值之間 3)range between unbounded preceding and value_expr preceding 表示式介於第一個值與當前行的值-value_expr之間,或者 表示式介於當前行的值-value_expr與第一個值之間 4)range between unbounded preceding and value_expr following 表示式介於第一個值與當前行的值+value_expr之間,或者 表示式介於當前行的值+value_expr與第一個值之間 5)range between current row and unbounded following 表示式介於當前行的值和最後一個值之間,或者 表示式介於最後一個值和當前行的值之間 6)range [between current row and] current row 表示式等於當前行的值 7)range between current row and value_expr following 表示式介於當前行的值和當前行的值+value_expr之間 8)range between value_expr preceding and unbounded following 表示式介於當前行的值-value_expr和最後一個值之間 9)range [between value_expr] preceding [and current row] 表示式介於當前行的值-value_expr和當前行的值之間 10)range between value_expr1 preceding and value_expr2 preceding 這裡一定要滿足value_expr1>=value_expr2。 然後表示式介於當前行的值-value_expr1和當前行的值-value_expr2之間 11)range between value_expr1 preceding and value_expr2 following 表示式介於當前行的值-value_expr1和當前行的值+value_expr2之間 12)range between value_expr following and unbounded following 表示式介於當前行的值+value_expr和最後一個值之間 表示式介於最後一個值和當前行的值+value_expr之間 13)range between value_expr1 following and value_expr2 following 這裡一定要滿足value_expr1<=value_expr2。 然後表示式介於當前行的值+value_expr1和當前行的值+value_expr2之間 14)range unbounded preceding 與2等價。 15)range current row 與6等價。 16)range value_expr preceding 與9等價。 注意事項: 1.若windowing_clause由rows指定,則: (1)value_expr是物理偏移量,它必須是常量或值為非負數的表示式。 (2)若value_expr是起點的一部分,那麼它必須在終點之前對行求值。 2.若windowing_clause由range指定,則: (1)value_expr是邏輯偏移量。它必須是常量或值為非負的表示式或時間間隔文字常量。 (2)value_expr值為一個數字,那麼order_by_clause中 expr必須為數字或date型別。 (3)value_expr為一個間隔值,那麼order_by_clause中expr必須是一個date型別。 3.若完全忽略windowing_clause,那麼預設的視窗範圍為 range between unbounded preceding and current row。 關於ROWS、RANGE中的條件組合加起來達到32種,但實際上不過是幾個關鍵字的排列組合而已,只要瞭解幾個關鍵字的含義,在應用時加以靈活使用即可。
SELECT emp_id,ename,dept_id,hire_date,sal, -- 後面均為以dept_id分組,再按hire_date排序,且所有統計不能跨分割槽,由於是邏輯範圍,因此PRECEDING和FOLLOWING表示式有符號 -- 視窗範圍為該分割槽的第一行到該分割槽的最後一行,與sum_sal_part等同,在非條件表示式中等同於ROWS SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) sum_1_to_last, -- 視窗範圍為該分割槽的第一行到本行,與sum_sal_part_order等同,在非條件表示式中等同於ROWS SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) sum_1_to_cur, -- 視窗範圍為該分割槽內小於本記錄sal少2500的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND 2500/*value_expr*/ PRECEDING) sum1, -- 視窗範圍為該分割槽內小於本記錄sal多2500的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND 2500/*value_expr*/ FOLLOWING) sum2 FROM emp; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM_1_TO_LAST SUM_1_TO_CUR SUM1 SUM2 ------ ----- ------- -------------- ----- ------------- ------------ ---------- ---------- 有數字,記住precding,就是減,following是加,就對了。 100 Stev 10 01-1月 -90 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 10000 2000 2000 解說SUM1(dept_id=50部分) 解說SUM2(dept_id=50部分) 102 Mike 20 13-1月 -93 8000 10000 10000 2000 10000 120 John 50 18-7月 -96 1000 19000 1000 4000 ---比1000-2500少的數字有木有,沒有 ---比1000+2500少的數字有木有,有啊,1000和3000 122 RICH 50 01-5月 -95 3000 19000 4000 13000 ---比3000-2500少的數字有木有,沒有,該組第1排的1000也比500大 ---比3000+2500少的數字有木有,有啊,1到4排都是 121 Joy 50 10-4月 -97 4000 19000 8000 1000 19000 ---比4000-2500少的數字有木有,有啊,該組第1排的1000就比1500小 ---比4000+2500少的數字有木有,有啊,該組都是 123 Kate 50 10-10月-97 5000 19000 13000 1000 19000 ---比5000-2500少的數字有木有,有啊,該組第1排的1000就比2500小 ---比5000+2500少的數字有木有,有啊,該組都是 124 Jess 50 16-11月-99 6000 19000 19000 4000 19000 ---比6000-2500少的數字有木有,有啊,該組第1排和第2排哦。 ---比6000+2500少的數字有木有,有啊,該組都是 SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為本行和該分割槽的最後一行,統計的是大於等於本記錄hire_date之後的所有薪資,在非條件表示式中等同於ROWS SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) sum3, -- 視窗範圍只是本行,所以與本行薪資一樣 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN CURRENT ROW AND CURRENT ROW) sum4, -- 視窗範圍為該分割槽內本記錄起和小於本記錄sal多2500的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN CURRENT ROW AND 2500/*value_expr*/ FOLLOWING) sum5, -- 視窗範圍為該分割槽內本記錄起和小於本記錄sal多2500的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 2500/*value_expr*/ PRECEDING AND UNBOUNDED FOLLOWING) sum6 FROM emp; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM3 SUM4 SUM5 SUM6 ------ ----- ------- -------------- ----- ---------- ---------- ---------- ---------- 100 Stev 10 01-1月 -90 7000 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 10000 2000 2000 10000 102 Mike 20 13-1月 -93 8000 8000 8000 8000 8000 120 John 50 18-7月 -96 1000 19000 1000 4000 19000 122 RICH 50 01-5月 -95 3000 18000 3000 12000 19000 121 Joy 50 10-4月 -97 4000 15000 4000 15000 18000 123 Kate 50 10-10月-97 5000 11000 5000 11000 18000 124 Jess 50 16-11月-99 6000 6000 6000 6000 15000 SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為該分割槽內大於本記錄sal少2500,並且截止到當前記錄的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 2500/*value_expr*/ PRECEDING AND CURRENT ROW) sum7, -- 視窗範圍為該分割槽的本行current_value-value_expr1到本行current_value-value_expr2的累計,強調value_expr1>=value_expr2 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 2500/*value_expr1*/ PRECEDING AND 1000/*value_expr2*/ PRECEDING) sum8, -- 視窗範圍為該分割槽的本行current_value-value_expr1到本行current_value+value_expr2之間的累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 2500/*value_expr1*/ PRECEDING AND 1000/*value_expr2*/ FOLLOWING) sum9, -- 視窗範圍為該分割槽內大於本記錄sal多2500的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 2500/*value_expr*/ FOLLOWING AND UNBOUNDED FOLLOWING) sum10 FROM emp; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM7 SUM8 SUM9 SUM10 ------ ----- ------- -------------- ----- ---------- ---------- ---------- ---------- 100 Stev 10 01-1月 -90 7000 7000 7000 101 Tom 20 21-9月 -89 2000 2000 2000 8000 解說SUM9 102 Mike 20 13-1月 -93 8000 8000 8000 120 John 50 18-7月 -96 1000 1000 1000 15000 ---有木有介於 1000-2500 到 1000+1000之間的數字,有,該組第一行1000就介於其中 122 RICH 50 01-5月 -95 3000 4000 1000 8000 6000 ---有木有介於 3000-2500 到 3000+1000之間的數字,有,該第1行到第3行都是,第3行正好符合 121 Joy 50 10-4月 -97 4000 7000 3000 12000 ---有木有介於 4000-2500 到 4000+1000之間的數字,有,該第2行到第4行都是,第4行正好符合 123 Kate 50 10-10月-97 5000 12000 7000 18000 ---有木有介於 5000-2500 到 5000+1000之間的數字,有,該第2行到第5行都是,第5行正好符合 124 Jess 50 16-11月-99 6000 15000 9000 15000 ---有木有介於 6000-2500 到 6000+1000之間的數字,有,該第3行到第5行都是 SELECT emp_id,ename,dept_id,hire_date,sal, -- 視窗範圍為該分割槽的本行current_value+value_expr1到本行current_value+value_expr2的累計,強調value_expr1<=value_expr2 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE BETWEEN 1000/*value_expr1*/ FOLLOWING AND 2500/*value_expr2*/ FOLLOWING) sum11, -- 視窗範圍為該分割槽的第一行,結束行預設為本行,與sum_sal_part_order,sum_2等同,在非條件表示式中等同於ROWS SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE UNBOUNDED PRECEDING) sum12, -- 視窗範圍僅為當前行,在非條件表示式中等同於ROWS SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE CURRENT ROW) sum13, -- 視窗範圍為該分割槽內大於本記錄sal少2500,並且截止到當前記錄的所有的薪資累計 SUM(sal) OVER (PARTITION BY dept_id ORDER BY sal RANGE 2500/*value_expr*/ PRECEDING) sum14 FROM emp; EMP_ID ENAME DEPT_ID HIRE_DATE SAL SUM11 SUM12 SUM13 SUM14 ------ ----- ------- -------------- ----- ---------- ---------- ---------- ---------- 100 Stev 10 01-1月 -90 7000 7000 7000 7000 101 Tom 20 21-9月 -89 2000 2000 2000 2000 102 Mike 20 13-1月 -93 8000 10000 8000 8000 120 John 50 18-7月 -96 1000 3000 1000 1000 1000 122 RICH 50 01-5月 -95 3000 9000 4000 3000 4000 121 Joy 50 10-4月 -97 4000 11000 8000 4000 7000 123 Kate 50 10-10月-97 5000 6000 13000 5000 12000 124 Jess 50 16-11月-99 6000 19000 6000 15000
KEEP視窗
聚合函式的特殊關鍵字KEEP
聚合函式MIN, MAX, SUM, AVG, COUNT, VARIANCE,和STDDEV, 當使用KEEP 時和DENSE_RANK FIRST /DENSE_RANK LAST一起使用,獲取一組中排名第一或者排名最後的記錄。必須有order by 子句用來排序。後面也可以接over()分析函式部分。
Min(col2)keep(dense_rank first order by col1)保留按col1排名第一的col2的最小值。
Min(col2)keep(dense_rank first order by col1)over (partition by col3) 按col3分組保留按col1排名各組第一的col2的最小值。
舉例說明:
---需要注意的是KEEP只能與DENSE_RANK FIRST、DENSE_RANK LAST搭配使用。
SELECT emp_id,ename,dept_id,hire_date,sal,
DENSE_RANK() OVER(PARTITION BY dept_id ORDER BY sal) DENSE_RANK,
MIN(hire_date) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER(PARTITION BY dept_id) min_first,
MIN(hire_date) KEEP (DENSE_RANK LAST ORDER BY sal) OVER(PARTITION BY dept_id) min_last,
MAX(hire_date) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER(PARTITION BY dept_id) max_first,
MAX(hire_date) KEEP (DENSE_RANK LAST ORDER BY sal) OVER(PARTITION BY dept_id) max_last
FROM emp;
EMP_ID ENAME DEPT_ID HIRE_DATE SAL DENSE_RANK MIN_FIRST MIN_LAST MAX_FIRST MAX_LAST
------ ----- ------- -------------- ----- ---------- -------------- -------------- -------------- -----------
100 Stev 10 01-1月 -90 7000 1 01-1月 -90 01-1月 -90 01-1月 -90 01-1月 -90
101 Tom 20 21-9月 -89 2000 1 21-9月 -89 13-1月 -93 21-9月 -89 13-1月 -93
102 Mike 20 13-1月 -93 8000 2 21-9月 -89 13-1月 -93 21-9月 -89 13-1月 -93
120 John 50 18-7月 -96 1000 1 18-7月 -96 16-11月-99 10-4月 -97 16-11月-99
121 Joy 50 10-4月 -97 1000 1 18-7月 -96 16-11月-99 10-4月 -97 16-11月-99
122 Rich 50 01-5月 -95 3000 2 18-7月 -96 16-11月-99 10-4月 -97 16-11月-99
123 Kate 50 10-10月-97 5000 3 18-7月 -96 16-11月-99 10-4月 -97 16-11月-99
124 Jess 50 16-11月-99 6000 4 18-7月 -96 16-11月-99 10-4月 -97 16-11月-99