高級函數_分析函數與窗口函數
分析函數往往與窗口函數一起使用,over()為窗口函數
一、分析函數
1.01、排名
分析函數中的排名函數可以針對窗口中的記錄生成排序序號,常用的排名函數有:rank()、dense_rank()、row_number()
語句:select * from employee;
EMP_ID ? ? ? ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? ? ? EMP_SALARY
------------------------ ------------------------------ ----------------------
0001 ? ? ? ? ? ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? ? ? ? ? ? 5000
0002 ? ? ? ? ? ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? ? ? ? ? ? 4500
0003 ? ? ? ? ? ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? ? ? ? ? ? 6000
0004 ? ? ? ? ? ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? ? ? ? ? ? 4500
0005 ? ? ? ? ? ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? ? ? ? ? ? 4500
0006 ? ? ? ? ? ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? ? ? ? ? ? 6000
語句:select emp_name,rank()over(order by emp_salary) position from employee;
EMP_NAME ? ? ? ? ?POSITION
--------------------- ?----------------------
王蘭 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
李四 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
韓明 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
張三 ? ? ? ? ? ? ? ? ? ? ? ? ? 4
李麗 ? ? ? ? ? ? ? ? ? ? ? ? ? 5趙飛 ? ? ? ? ? ? ? ? ? ? ? ? ? 5
rank()函數對于相同排名的記錄,會返回相同的排序序號,當出現多個排名?相同的記錄時,下一排名序號,將根據前一排名個數進行跳躍,如里面沒有出現2和3,直接跳到4
語句:select emp_name,dense_rank()over(order by emp_salary) position from employee;
EMP_NAME ? ? ? ? ? ??POSITION
------------------------?----------------------
王蘭 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
李四 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
韓明 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
張三 ? ? ? ? ? ? ? ? ? ? ? ? ? 2
李麗 ? ? ? ? ? ? ? ? ? ? ? ? ? 3
趙飛 ? ? ? ? ? ? ? ? ? ? ? ? ? 3
dense_rank()函數對于相同排名的記錄,會返回相同的排序序號,當出現多個排名?相同的記錄時,不會進行跳躍
語句:select emp_name,row_number() over(order by emp_salary) position from employee;
EMP_NAME ? ? ? ? ? ? ??POSITION
------------------------ ----------------------
王蘭 ? ? ? ? ? ? ? ? ? ? ? ? ? 1
李四 ? ? ? ? ? ? ? ? ? ? ? ? ? 2
韓明 ? ? ? ? ? ? ? ? ? ? ? ? ? 3
張三 ? ? ? ? ? ? ? ? ? ? ? ? ? 4
李麗 ? ? ? ? ? ? ? ? ? ? ? ? ? 5
趙飛 ? ? ? ? ? ? ? ? ? ? ? ? ? 6row_number()函數每條記錄會存在唯一的排序序號
二、分區窗口
利用partition by 可以指定?分區窗口
語句:?select * from employee;
EMP_ID ? ? ? ? ? ? EMP_NAME ? ? ?EMP_SALARY ? ?EMP_DEPARTMENT
-------------------- -----------------?---------------------- --------------------
0001 ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? 5000 ? ? ? ? ? ? ? ? ? 設計部
0002 ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部
0003 ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
0004 ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 項目部
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部
0006 ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
語句:select t.*,dense_rank() over(partition byemp_department order by emp_salary) position from employee t order by t.emp_id;
EMP_ID ? ? ? ? ? ???EMP_NAME ? ? ? ??EMP_SALARY ? ? ? ? ??EMP_DEPARTMENT ? ? ? POSITION
-------------------- -------------------- ---------------------- -------------------- - ? ? ? ? ? ? ? ? ---------------------
0001 ? ? ? ? ? ? ? ? ??張三 ? ? ? ? ? ? ? ? ? ? ?5000 ? ? ? ? ? ? ? ? ? ? ? ? ??設計部 ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ?1
0002 ? ? ? ? ? ? ? ? ??李四 ? ? ? ? ? ? ? ? ? ? ?4500 ? ? ? ? ? ? ? ? ? ? ? ? ??工程部10003 ? ? ? ? ? ? ? ? ??趙飛 ? ? ? ? ? ? ? ? ? ???6000項目部20004 ? ? ? ? ? ? ? ? ??韓明 ? ? ? ? ? ? ? ? ? ? ?4500項目部10005 ? ? ? ? ? ? ? ? ??王蘭 ? ? ? ? ? ? ? ? ? ? ?4500工程部10006 ? ? ? ? ? ? ? ?? ?李麗 ? ? ? ? ? ? ? ? ? ? ?6000項目部2
分區內可以求和
語句:select t.*,sum(emp_salary)over(partition byemp_department ) position from employee t order by t.emp_id;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? ??EMP_DEPARTMENT ? ? ? TOTAL_SALARY
-------------------- -------------------- ---------------------- ? ? ? ? ??-------------------- ? ? ? ? ? ? ? ? ??---------------------
0001 ? ? ? ? ? ? ? ? ? ??張三 ? ? ? ? ? ? ? ? ? ? ???5000 ? ? ? ? ? ? ? ? ? ? ? ? ? 設計部 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 5000
0002李四4500工程部9000
0003趙飛6000項目部16500
0004韓明4500項目部16500
0005王蘭4500工程部9000
0006李麗6000項目部16500
三、窗口子句
可以使用窗口子句來進一步控制窗口的范圍,包含兩類:rows和range
3.01、rows子句
rows子句以當前記錄為參照,可以向前向后推移,形成新的結果集
語句:select emp_id,emp_name,emp_salary,sum(emp_salary) over(order by emp_id rows between 1 preceding and 1 following) total_salary from employee;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? TOTAL_SALARY
-------------------- -------------------- ---------------------- ? ? ? ? ? ----------------------
0001 ? ? ? ? ? ? ? ? ? ??張三 ? ? ? ? ? ? ? ? ? ? ?? ?5000 ? ? ? ? ? ? ? ? ? ? ? ???9500
0002李四450015500
0003趙飛600015000
0004韓明450015000
0005王蘭450015000
0006李麗600010500
rows子句因為和位置有關,必須使用order by排序,否則報錯
3.02、range子句range子句按照列值進行窗口的進一步限制
語句:select emp_id,emp_name,emp_salary,count(1) over(order by emp_salary range between 300 preceding and 400 following) total_count from employee;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? ? ? TOTAL_COUNT
-------------------- -------------------- ---------------------- ? ? ? ? ? ? ? ----------------------
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? ? ? ? ? ???4500 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3
0002 ? ? ? ? ? ? ? ? 李四450030004 ? ? ? ? ? ? ? ? 韓明450030001 ? ? ? ? ? ? ? ? 張三500010006 ? ? ? ? ? ? ? ? 李麗600020003 ? ? ? ? ? ? ? ? 趙飛60002
3.03、unbouned和 current row
unbouned表示沒有任何限制,current row代表當前行
四、主要的分析函數
分析函數作用對象為窗口函數所捕獲的記錄集合
4.01?、first_value()函數的使用first_value()函數用于獲取窗口函數所捕獲的記錄集中的第一條記錄,并根據第一條記錄返回返回表達式參數的值
語句:?select * from employee;
EMP_ID ? ? ? ? ? ? EMP_NAME ? ? ?EMP_SALARY ? ?EMP_DEPARTMENT
-------------------- -----------------?---------------------- --------------------
0001 ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? 5000 ? ? ? ? ? ? ? ? ? 設計部
0002 ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部
0003 ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
0004 ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 項目部
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部
0006 ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
語句:select distinctemp_department,first_value(emp_name) over(partition by emp_department order by emp_salary)minname,
first_value(emp_salary) over(partition by emp_department order by emp_salary)minsalary ?from employee;
EMP_DEPARTMENT ? ? ? MINNAME ? ? ? ? ? ? ?MINSALARY
-------------------- ? ? ? ? ? ? ? ?-------------------- ----------------------
設計部 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? ? ??5000
項目部韓明4500
工程部李四4500
備注:distinct關鍵字是必要的,查詢每部門工資最少的人 ,人名和工資都要用first_value()函數,每一列都是一個結果集,互不影響,若有一個不加,不加的會顯示所有的值,結果如下:
語句:select distinct emp_department, first_value(emp_name) over(partition by emp_department order by emp_salary) minname,emp_salary from employee;
EMP_DEPARTMENT ? ? ? MINNAME ? ? ? ? ? ? ?EMP_SALARY
-------------------- ? ? ? ? ? ? ??-------------------- ----------------------
工程部 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ?? ? ?4500
設計部張三5000項目部韓明4500
項目部韓明6000
4.02?、last_value()函數的使用
last_value()函數返回窗口中的最后一條記錄的相關信息
語句:select distinct last_value(emp_name) over(partition by emp_department order by emp_salary rows between unbounded preceding and unbounded following) maxname,emp_department,
last_value(emp_salary) over(partition by emp_department order by emp_salaryrows between unbounded preceding and unbounded following) maxsalary ?from employee;
MAXNAME ? ? ? ? ? ? ?EMP_DEPARTMENT ? ? ? MAXSALARY
-------------------- -------------------- ? ? ? ? ? ? ? ? ?----------------------
張三 ? ? ? ? ? ? ? ? ??? ?設計部 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5000
趙飛項目部6000李四工程部4500
備注:窗口函數中必須使用rows between unbounded preceding and unbounded following,因為默認情況下,order by 窗口為第一條記錄至當前記錄,對于order by 子句,如果沒有顯示指定rows和range子句,則相當于使用了rows between unbounded preceding and current row following或者range between unbounded preceding andcurrent rowfollowing,當排序后存在相同的排名,則所有相同的記錄放到被刷選的窗口中,值不同會放到不同的窗口,未使用的結果如下:
語句:select distinct last_value(emp_name) over(partition by emp_department order by emp_salary) maxname,emp_department,
last_value(emp_salary) over(partition by emp_department order by emp_salary) maxsalary ?from employee;
MAXNAME ? ? ? ? ? ? ?EMP_DEPARTMENT ? ? ? MAXSALARY
-------------------- -------------------- ? ? ? ? ? ? ? ?----------------------
張三 ? ? ? ? ? ? ? ? ? ? ??設計部 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5000
韓明項目部4500趙飛項目部6000王蘭工程部4500
4.03 、lead()函數的使用
lead()函數對于通過排序之后的窗口集合,lead()函數自當前記錄向下推移,獲得新的記錄
語法:lead(表達式,偏移量,替換值)?其中替換值是當無法獲取新紀錄時,用該值替換
語句:select emp_id,emp_name,emp_salary,emp_department from employee order by emp_id;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? ? ? EMP_DEPARTMENT
-------------------- -------------------- ---------------------- --------------------
0001 ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? 5000 ? ? ? ? ? ? ? ? ? 設計部
0002 ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部
0003 ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
0004 ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 項目部
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? 4600 ? ? ? ? ? ? ? ? ? 工程部
0006 ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部
語句:select emp_id,emp_name,emp_salary,emp_department,lead(emp_name,1,'無') over(partition by emp_department order by emp_salary) pre_name from employee order by emp_id;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? ? ? EMP_DEPARTMENT ? ? ? PRE_NAME
-------------------- -------------------- ---------------------- -------------------- --------------------
0001 ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? 5000 ? ? ? ? ? ? ? ? ? 設計部 ? ? ? ? ? ? ? 無
0002 ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部 ? ? ? ? ? ? ? 王蘭
0003 ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 無
0004 ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 李麗
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? 4600 ? ? ? ? ? ? ? ? ? 工程部 ? ? ? ? ? ? ? 無0006 ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 趙飛
4.04 、lag()函數的使用
lag()函數與lead()函數具有相同的語法規則,在排序之后,lag()函數自當前記錄向上搜索
語法:select emp_id,emp_name,emp_salary,emp_department,lag(emp_name,1,'無') over(partition by emp_department order by emp_salary) pre_name from employee order by emp_id;
EMP_ID ? ? ? ? ? ? ? EMP_NAME ? ? ? ? ? ? EMP_SALARY ? ? ? ? ? ? EMP_DEPARTMENT ? ? ? PRE_NAME
-------------------- -------------------- ---------------------- -------------------- --------------------
0001 ? ? ? ? ? ? ? ? 張三 ? ? ? ? ? ? ? ? 5000 ? ? ? ? ? ? ? ? ? 設計部 ? ? ? ? ? ? ? 無
0002 ? ? ? ? ? ? ? ? 李四 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 工程部 ? ? ? ? ? ? ? 無
0003 ? ? ? ? ? ? ? ? 趙飛 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 李麗
0004 ? ? ? ? ? ? ? ? 韓明 ? ? ? ? ? ? ? ? 4500 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 無
0005 ? ? ? ? ? ? ? ? 王蘭 ? ? ? ? ? ? ? ? 4600 ? ? ? ? ? ? ? ? ? 工程部 ? ? ? ? ? ? ? 李四
0006 ? ? ? ? ? ? ? ? 李麗 ? ? ? ? ? ? ? ? 6000 ? ? ? ? ? ? ? ? ? 項目部 ? ? ? ? ? ? ? 韓明