SQL中的開窗函式詳解可代替聚合函式使用

2022-09-26 11:51:14 字數 2375 閱讀 2046

在沒學習開窗函式之前,我們都知道,用了分組之後,查詢欄位就只能是分組欄位和聚合的字段,這帶來了極大的不方便,有時我們查詢時需要分組,又需要查詢不分組的字段,每次都要又到子查詢,這樣顯得sql語句複雜難懂,給維護**的人帶來很大的痛苦,然而開窗函式出現了,曙光也來臨了。如果要想更具體了解開窗函式,請看書《程式設計師的sql金典》,開窗函式在mysql不能使用。

開窗函式與聚合函式一樣,都是對行的集合組進行聚合計算。它用於為行定義乙個視窗(這裡的視窗是指運算將要操作的行的集合),它對一組值進行操作,不需要使用group by語句對資料進行分組,能夠在同一行中同時返回基礎行的列和聚合列。定義看不懂不要緊,會用就行。

舉個簡單例子 查詢每個工資小於5000的員工資訊(姓名,城市 年齡 薪水),並且顯示小於5000的員工個數,嘗試使用下面語句:

select fname, fcity, fage, fsalary, count(fname) from t_person where fsalary<5000

訊息 8120,級別 16,狀態 1,第 1 行

選擇列表中的列 't_person.fname' 無效,因為該列沒有包含在聚合函式或 group by 子句中。

可以使用子查詢實現,語句:

select fname, fcity, fage, fsalary, ( select count(fname) from t_person where fsalary<5000 ) personnum from t_person

where fsalary<5000

結果:使用開窗函式實現,查詢結果一模一樣,就不貼上了:

select fname, fcity, fage, fsalary, count(fname) over() as personnum from t_person

where fsalary<5000

1.開窗函式格式:函式名(列) over(選項)

2.聚合開窗函式格式:聚合函式(列) over(partition by 字段)

over關鍵字把聚合函式當成聚合開窗函式而不是聚合函式,sql標準允許將所有的聚合函式用做聚合開窗函式。over關鍵字後的括號中還經常新增選項用程式設計客棧以改變進行聚合運算的視窗範圍。如果over關鍵字後的括號為空,則開窗函式會對結果集合的所有行進行聚合運算。

partition by來定義行的分割槽來進行聚合運算,與group by 不同,partition by 字句建立的分割槽是獨立於結果集的,建立的分割槽只是用於進行聚合運算,而且不同的開窗函式所建立的分割槽不互相影響,例如:查詢所有人員的資訊,並查詢所屬城市的人員數以及同年齡的人員數:

select fname,fcity, fage, fsalary, count(fname) over(partition by fcity) citynum,

count(fname) over(partition by fage) agenum from t_person order by fcity

查詢所有人員的資訊,並查詢所屬城市的人員數,每個城市的人按照年齡排序語句:

select f程式設計客棧name,fcity, fage, fsalary, count(fname) over(partition by fcity order by fage) citynum from t_person

3.排序開窗函式格式:排序函式() over(order by 字段)

(1)主要函式有row_number()、rank()、dense_rank()、ntile()

row_number() 加行號,一般可以用於分頁查詢(現在被offset  fetch取代 ),對於沒有主鍵列的表加行號作用很明顯,刪除重複資料等。

按照薪水高低給所有人員排序,同樣薪水的排名不一樣,可以用row_number(),

with a as

(select fname, fsalary, fcity, fage, row_number() over(order by fsalary) as rownum from t_person

)select * from a

使用rank()將每個城市的薪水排行,值一樣的同乙個排名,出現兩個第一名的時候,排在兩個第一名後的排名將是第三名

select fname, fsalary, fcity, fage, rank() over(partition by fcity order by fsalary) as ranknum from t_person

使用dense_rank()將每個城市的薪水排行,值一樣的同乙個排名,出現兩個第一名的時候,排在兩個第一名後的排名將是第三lpvafvgrmq名

ntile(數字)程式設計客棧 over(order by 字段):數字表示一組多少個數,並根據數量得出分組的數量

select *,ntile(5) over(order by fsalary) as nilenum from t_person

Spark SQL中開窗函式詳解

row number 開窗函式 其實就是給每個分組的資料,按照其排序的順序,打上乙個分組內的行號,相當於grouptopn,在實際應用中非常廣泛。deptname name salary dept 1 michael 3000 dept 2 andy 5000 dept 1 alex 4500 de...

SQL 開窗函式 range和rows的區別

range基於order by的值計算,如圖一,order by的值為20190101 rows基於order by排好的順序的行計算,如圖二,計算排序後的行 range可應用於訂單日期 rows可應用於訂單筆數 圖一注意 第乙個視窗第2行金額425的時間計算範圍是 20190101 2019010...

oracle中的開窗函式理解

開窗函式指定了分析函式工作的資料視窗大小,這個資料視窗大小可能會隨著行的變化而變化,舉例如下 over order by salary 按照salary排序進行累計,order by是個預設的開窗函式 over partition by deptno 按照部門分割槽 over order by sa...