在開窗函式出現之前存在著非常多用 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 等主流資料庫中都提...