深入淺出談開窗函式(一)

2021-09-06 19:11:23 字數 4385 閱讀 9677

在開窗函式出現之前存在著非常多用 sql 語句非常難解決的問題,非常多都要通過複雜的相關子查詢或者儲存過程來完畢。為了解決這些問題,在2023年iso  sql標準增加了開窗函式,開窗函式的使用使得這些經典的難題能夠被輕鬆的解決。眼下在 mssqlserver、oracle、db2 等主流資料庫中都提供了對開窗函式的支援,只是非常遺憾的是 mysql 臨時還未對開窗函式給予支援。

為了更加清楚地理解,我們來建表並進行相關的查詢(截圖為mssqlserver中的結果)

mysql,mssqlserver,db2:

create table t_person 

( fname varchar(20),

fcity varchar(20),

fage int,

fsalary int

)

oracle: 

create table t_person (fname varchar2(20),fcity varchar2(20), fage int,fsalary int) 

注:下面結果僅僅在mssqlserver中演示:

t_person 表儲存了人員資訊,fname 欄位為人員姓名,fcity 欄位為人員所在的城市名,

fage  欄位為人員年齡,fsalary 欄位為人員工資。然後執行以下的sql語句向 t_person

表中插入一些演示資料:

insert into t_person(fname,fcity,fage,fsalary) 

values('tom','beijing',20,3000);

insert into t_person(fname,fcity,fage,fsalary)

values('tim','chengdu',21,4000);

insert into t_person(fname,fcity,fage,fsalary)

values('jim','beijing',22,3500);

insert into t_person(fname,fcity,fage,fsalary)

values('lily','london',21,2000);

insert into t_person(fname,fcity,fage,fsalary)

values('john','newyork',22,1000);

insert into t_person(fname,fcity,fage,fsalary)

values('yaoming','beijing',20,3000);

insert into t_person(fname,fcity,fage,fsalary)

values('swing','london',22,2000);

insert into t_person(fname,fcity,fage,fsalary)

values('guo','newyork',20,2800);

insert into t_person(fname,fcity,fage,fsalary)

values('yuqian','beijing',24,8000);

insert into t_person(fname,fcity,fage,fsalary)

values('ketty','london',25,8500);

insert into t_person(fname,fcity,fage,fsalary)

values('kitty','chengdu',25,3000);

insert into t_person(fname,fcity,fage,fsalary)

values('merry','beijing',23,3500);

insert into t_person(fname,fcity,fage,fsalary)

values('smith','chengdu',30,3000);

insert into t_person(fname,fcity,fage,fsalary)

values('bill','beijing',25,2000);

insert into t_person(fname,fcity,fage,fsalary)

values('jerry','newyork',24,3300);

檢視表中的內容:

開窗函式簡單介紹 

與 聚 合函式一樣,開窗函式也是對行集組進行聚合計算,可是它不像普通聚合函式那樣

每組僅僅返回乙個值,開窗函式能夠為每組返回多個值,由於開窗函式所執行聚合計算的行

集組是窗體。在iso sql規定了這種函式為開窗函式,在 oracle中則被稱為分析函式,

而在db2中則被稱為olap函式。  

要計算全部人員的總數,我們能夠執行以下的 sql語句: 

select count(*) from t_person 

除了這樣的較簡單的使用方式, 有時須要從不在聚合函式中的行中訪問這些聚合計

算的值。比方我們想查詢每乙個工資小於 5000元的員工資訊(城市以及年齡) ,而且在

每行中都顯示全部工資小於5000元的員工個數,嘗試編寫以下的 sql語句: 

select fcity , fage , count(*)  

from t_person 

here fsalary<5000 

執行上面的sql以後我們會得到以下的錯誤資訊: 

選擇列表中的列  't_person.fcity' 無效,由於該列沒有包括在聚合函式或 

group by 子句中。 

這是由於全部不包括在聚合函式中的列必須宣告在group by 子句中,

能夠進行例如以下改動: 

select fcity, fage, count(*)  

from t_person 

where fsalary<5000 

group by fcity , fage 

執行完成我們就能在輸出結果中看到以下的執行結果:                

這個執行結果與我們想像的是全然不同的,這是由於group  by子句對結果集

進行了分組,所以聚合函式進行計算的物件不再是全部的結果集,而是每個分組。

能夠通過子查詢來解決問題,sql例如以下: 

select fcity , fage ,  

( select count(* ) from t_person 

where fsalary<5000 

) from t_person 

where fsalary<5000 

執行完成我們就能在輸出結果中看到以下的執行結果:

儘管使用子查詢可以解決問題,可是子查詢的使用很麻煩,使用開窗函式

則能夠大大簡化實現,以下的sql語句展示了假設使用開窗函式來實現相同的效果: 

select fcity , fage , count(*) over() 

from t_person 

where fsalary<5000 

執行完成我們就能在輸出結果中看到以下的執行結果: 

能夠看到與聚合函式不同的是,開窗函式在聚合函式後新增了乙個over keyword。 

開窗函式的呼叫格式為: 

函式名(列) over(選項) 

over   keyword表示把函式當成開窗函式而不是聚合函式。sql  標準同意將全部聚 

合函式用做開窗函式,使用over keyword來區分這兩種使用方法。 

在上邊的樣例中,開窗函式count(*) over()對於查詢結果的每一行都返回全部 

符合條件的行的條數。overkeyword後的括號裡還常常加入選項用以改變進行聚合運算的窗 

口範圍。假設overkeyword後的括號裡的選項為空,則開窗函式會對結果集中的全部行進行 

聚合運算。    

深入淺出談開窗函式(一)

在開窗函式出現之前存在著很多用 sql 語句很難解決的問題,很多都要通過複雜的相關子查詢或者儲存過程來完成。為了解決這些問題,在2003年iso sql標準加入了開窗函式,開窗函式的使用使得這些經典的難題可以被輕鬆的解決。目前在 mssqlserver oracle db2 等主流資料庫中都提供了對...

深入淺出談開窗函式(一)

在開窗函式出現之前存在著非常多用 sql 語句非常難解決的問題,非常多都要通過複雜的相關子查詢或者儲存過程來完畢。為了解決這些問題,在2003年iso sql標準增加了開窗函式,開窗函式的使用使得這些經典的難題能夠被輕鬆的解決。眼下在 mssqlserver oracle db2 等主流資料庫中都提...

深入淺出談開窗函式(一)

在開窗函式出現之前存在著非常多用 sql 語句非常難解決的問題,非常多都要通過複雜的相關子查詢或者儲存過程來完畢。為了解決這些問題,在2003年iso sql標準添 了開窗函式,開窗函式的使用使得這些經典的難題能夠被輕鬆的解決。眼下在 mssqlserver oracle db2 等主流資料庫中都提...