文章轉載自「開發者圓桌」一個關於開發者入門、進階、踩坑的微信公衆號數據庫
數據庫中的函數封裝了一些通用的功能,例如日期類型和字符串類型之間的轉換,每一個數據庫系統都內置了一些函數,固然用戶也能夠自定義函數。微信
在Oracle數據庫中,函數可總分爲單行函數、分組函數「亦稱聚合函數」、分析函數三類。ide
單行函數函數
單行函數分爲五種類型:字符函數、數值函數、日期函數、轉換函數、通用函數。好比:測試
--大小寫控制函數 spa
select lower('Hello World') 轉小寫, upper('Hello World') 轉大寫 from dual; 3d
--initcap: 首字母大寫 orm
select initcap('hello world') 首字符大寫 from dual; blog
--字符控制函數 排序
-- concat: 字符鏈接函數, 等同於 ||
select concat('Hello',' World') from dual;
分組函數
分組函數「亦稱聚合函數」能在select或select的having子句中使用,當用於select子串時經常都和GROUP BY一塊兒使用。多行函數分爲接收多個輸入,返回一個輸出。好比:
--分組數據:求各個部門的平均工資
select deptno,avg(sal) from emp group by deptno;
--group by做用於多列: 按部門,不一樣的工種,統計平均工資
--group by做用於多列:先按照第一列分組;若是相同,再按照第二列分組
select deptno,job,avg(sal) from emp group by deptno,job;
--:求部門的平均工資大於2000的部門
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
分析函數
分析函數是Oracle專門用於解決複雜報表統計需求的功能強大的函數,它能夠在數據中進行分組而後計算基於組的某種統計值,而且每一組的每一行均可以返回一個統計值,爲咱們分析數據提供了一種簡單高效的處理方式。
在分析函數出現之前,咱們必須使用自聯查詢,子查詢或者內聯視圖,甚至複雜的存儲過程實現的語句,如今只要一條簡單的SQL語句就能夠實現了,並且在執行效率方面也有至關大的提升。
分析函數和分組函數的不一樣
普通的分組函數用group by分組,每一個分組返回一個統計值,而分析函數採用partition by分組,而且每組每行均可以返回一個統計值。
分析函數的形式
經常使用的分析函數以下所列:
row_number() over(partition by ... order by ...)
rank() over(partition by ... order by ...)
dense_rank() over(partition by ... order by ...)
count() over(partition by ... order by ...)
max() over(partition by ... order by ...)
min() over(partition by ... order by ...)
sum() over(partition by ... order by ...)
avg() over(partition by ... order by ...)
first_value() over(partition by ... order by ...)
last_value() over(partition by ... order by ...)
lag() over(partition by ... order by ...)
lead() over(partition by ... order by ...)
分析函數常見應用場景
通常能夠解決這樣的問題:
①查找上一年度各個銷售區域排名前10的員工
②按區域查找上一年度訂單總額佔區域訂單總額20%以上的客戶
③查找上一年度銷售最差的部門所在的區域
④查找上一年度銷售最好和最差的產品
咱們看看上面的幾個問題就能夠感受到這幾個查詢和咱們平常遇到的查詢有些不一樣,具體有:
①須要對一樣的數據進行不一樣級別的聚合操做
②須要在表內將多條數據和同一條數據進行屢次的比較
③須要在排序完的結果集上進行額外的過濾操做
分析函數初體驗
簡單介紹幾個分析函數的使用樣例,讓你們可以近距離體驗一下Oracle分析函數的強大,Oracle的資料仍是比較好找的「相對於DB2來講」,搜索「Oracle分析函數」關鍵字便可獲取更多相關用法,這些樣例均在scott用戶下成功運行。
例1,顯示各部門員工的工資,並附帶顯示該部門的最高工資
執行SQL
select e.deptno,
e.empno,
e.ename,
e.sal,
last_value(e.sal)
over(partition by e.deptno
order by e.sal rows
--unbounded preceding and unbouned following針對當前全部記錄的前一條、後一條記錄,也就是表中的全部記錄
--unbounded:不受控制的,無限的
--preceding:在...以前
--following:在...以後
between unbounded preceding and unbounded following) max_sal
from emp e;
運行結果
例2,按照deptno分組,而後計算每組值的總和
執行SQL
select empno,
ename,
deptno,
sal,
sum(sal) over(partition by deptno order by ename) max_sal
from emp;
運行結果
例3,當前行的上一行(rownum-1)到當前行的下輛行(rownum+2)的彙總
執行SQL
select empno,
ename,
deptno,
sal,
--注意rows between 1 preceding and 1 following 是指當前行的上一行(rownum-1)到當前行的下輛行(rownum+2)的彙總
sum(sal) over(partition by deptno
order by ename
rows between 1 preceding and 2 following) max_sal
from emp;
運行結果
例4,終極測試
執行SQL
select
deptno 部門編號,ename 員工姓名,sal 薪水,
avg(sal) over(partition by deptno) 該部門薪水均值,
sum(sal) over(partition by deptno) 該部門薪水總額,
count(sal) over(partition by deptno) 部門員工數量,
dense_rank() over(partition by deptno order by sal desc) 該人員的部門薪水排行1,
row_number() over(partition by deptno order by sal desc) 該人員的部門薪水排行2,
dense_rank() over(order by sal desc) 該人員的全公司薪水排行,
min(sal) over(partition by deptno) 該部門的最低薪水1 ,
min(sal) keep(dense_rank first order by sal) over(partition by deptno) 該部門的最低薪水2 ,
first_value(sal) over(partition by deptno order by sal) 該部門的最低薪水3,
max(sal) over(partition by deptno) 該部門的最高薪水1,
max(sal) keep(dense_rank last order by sal) over(partition by deptno) 該部門的最高薪水2,
last_value(sal) over(partition by deptno order by sal) 該部門的最高薪水3,
last_value(sal) over(partition by deptno order by sal rows between unbounded preceding and unbounded following ) 該部門的最高薪水4,
lag(ename, 1, '00') over(order by sal desc) 薪水在本身前一位的人,
lead(ename, 1, '00') over(order by sal desc) 薪水在本身後一位的人
from emp e
order by deptno,sal,ename
運行結果
注意:
「該部門的最高薪水1\2\3」等結果是同樣的,只是使用了不一樣的寫法而已。
last_value()的不一樣寫法致使「該部門的最高薪水3」和「該部門的最高薪水4」結果是不一樣的,能夠這樣去理解:last_value()默認統計範圍是 rows between unbounded preceding and current row,所以須要加上rows between unbounded preceding and unbounded following ,才能獲得正確的統計結果,「該部門的最高薪水4」的統計結果纔是正確的。