在工作的過程中,我們有時候需要編寫複雜的sql腳本.在這個時候,如果掌握一些數據庫函數,對我們的工作可以事半功倍的作用. 這篇主要記錄學習Oracle 的窗口函數的一些體會.
窗口函數的名字是over()函數,常用的有兩個屬性partition by和order by,partition by類似於group by,我們通常將group by叫做分組,而partition by稱作分區,分組返回通常是一行,partition by返回的是多行。
窗口函數的威力是與其他函數聯合使用,窗口函數主要和統計函數,排名函數,錯行的函數聯合使用.
1.和統計函數(max,min,avg,sum等)連用.比如現在有一個簡單的例子,查詢每個同學單科成績和班級相應單科成績的差值.結果是這樣,張三語文+1,張三數學-1.代表了張三語文比班級語文均分高一分,數學成績比班級均分少一分.這是一個簡單的需求.測試數據如下
我們可以使用傳統的group by 來查出每門功課的平均分,然後查出差值,sql腳本如下
select t1.*, (t1.score - t3.avgs) as gaps
from test_student_score t1,
(select t2.subject_id, avg(t2.score) as avgs
from test_student_score t2
group by t2.subject_id) t3
where t1.subject_id = t3.subject_id;
- 1
- 2
- 3
- 4
- 5
- 6
如果是使用over 窗口函數,這個sql就變成了一行代碼,如下
select t.*,
(t.score-avg(t.score) over( partition by t.subject_id)) as gaps
from test_student_score t
- 1
- 2
- 3
上面兩句腳本都得到如下結果
2.和排名函數(rank,dense_rank)連用.先說明連個函數的意義:rank是不連續排名函數(1,1,3,3,5),dense_rank 是連續排名函數(1,1,2,2,3).
例:查出科目3 各同學成績排名情況
2.1使用不連續排名rank()
select t.*, rank() over(order by t.score desc) as ranks
from test_student_score t
where t.subject_id = 3;
- 1
- 2
- 3
得到的結果
2.2使用連續排名dense_rank()
select t.*, dense_rank() over(order by t.score desc) as ranks
from test_student_score t
where t.subject_id = 3;
- 1
- 2
- 3
結果如下
3.和錯行函數(lag,lead)聯合使用.lag上幾行,lead 下幾行
/*語法*/
lag(exp_str,offset,defval) over()
Lead(exp_str,offset,defval) over()
--exp_str要取的列
--offset取偏移後的第幾行數據
--defval:沒有符合條件的默認值
- 1
- 2
- 3
- 4
- 5
- 6
測試數據
select * from test_student_score t where t.subject_id = 3;
查上一行和下一行數據
select t.subject_id,
t.subject_id,
lag(t.score, 1, -1) over(order by t.score) as lags,
t.score,
lead(t.score, 1, -1) over(order by t.score) as leads
from test_student_score t
where t.subject_id = 3;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
以上就是Oracle 窗口函數的幾個簡單的應用.