前言摘要:本文由葡萄城技術團隊于博客園原創并首發。轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
SQL語句中,聚合函數在統計業務數據結果時起到了重要作用,比如計算每個業務地區的業務總數、每個班級的學生平均分以及每個分類的最大值等。然而,今天我將介紹窗口函數,與聚合函數相比,它們也是一組函數,但在使用方法和適用場景上有所不同。在本章節中,我將重點介紹窗口函數中的RANK和DENSE_RANK函數,以及它們在排名和篩選方面的應用場景。這些窗口函數可以幫助我們更靈活地處理數據并獲得所需的結果,需要注意的是,目前主流的數據庫對窗口函數的最低需求版本如下:
Mysql (>=8.0)PostgreSQL(>=8.4)SQL Server(>2005)SQLite(>3.25.0)
(資料圖片)
如果您的數據庫版本低于上述要求,將無法使用窗口函數。
需求背景:為了讓大家更好的理解,我將以學生數據作為查詢的條件背景:假設現在某個學校的某個年級的同學完成了一次考試,成績也已經錄入到數據庫中:
現在該年級的教務主任想要看一下:
1.這次考試本年級各個科目的前2名的同學。
2.這次考試每個班級中各個科目的前2名。
3.這次考試每個班級中的總分排名前2名。
如果用普通的SQL查詢即麻煩也費時間,而使用RANK和DENSE_RANK函數就可以很快的查詢出想要的學生數據,下面將為大家介紹如何使用RANK和DENSE_RANK函數實現學生數據的查詢。
使用聚RANK和DENSE_RANK函數查詢學生數據1.查詢本年級各個科目前2名的同學。為了獲得各個不同科目各自的前2名,我們需要先使用 Rank() 函數來給每個學生在各自科目的分區打上成績排名, 執行如下SQL 語句,查詢出來的結果如下圖。
select sd.*, RANK() over(partition by subject order by score desc) as _rank from score_data sd;
可以看到,執行結果里面已經根據各個科目的成績得到了排名字段 _rank, 接下來只需要使用過濾掉 _rank 字段大于2的部分即可,查詢的結果如下圖所示。
select * from (select sd.*, RANK() over(partition by subject order by score desc) as _rank from score_data sd) tmpwhere tmp._rank <=2
從上圖中看到如果存在成績一樣的情況,就會出現像數學科目的查詢結果:數學查詢出來了三個值(因為有兩個人的數學成績是一樣的77分),如果我們只想保留一條重復的數據,我們可以使用DENSE_RANK函數,這個函數的計算語法和 RANK 基本一致,唯一不同的點在于, Rank 計算時會得到成績高于當前行的記錄的總行數,也就是上圖查詢出來的數學科目的三條數據,而DENSE_RANK 則是計算成績高于當前行的去重記錄的總行數,也就是說,如果出現像上圖的數學科目中的重復的數據,就會去掉重復的數據。
2.查詢每個班級中各個科目的前2名。查詢每個班級中各個科目的前2名只需要在第一步(查詢本年級各個科目前2名的同學)的加上一個 class 班級的分區規則即可,查詢的結果如下圖所示:
select * from (select sd.*, RANK() over(partition by subject, class order by score desc) as _rank from score_data sd) tmpwhere tmp._rank <=2
3. 查詢每個班級中的總分排名前2名。同理,在第二步(查詢score_data表中每個班級中各個科目的前2名)的基礎上再添加一個成績的總和SUM(score)函數即可查詢每個班級中的總分前兩名。
select class,name,SUM(score) AS total_score,RANK() over (PARTITION by class order by SUM(score) desc)from score_data sd group by class,name
在這個指標的計算中,需要把聚合函數和排名函數結合起來使用,因為每個人的總成績被拆分為了多個科目的和,所以需要在班級和科目的聯合分組維度上進行聚合,把數據壓縮到每人總分的顆粒度。
總結窗口函數是 SQL 函數中非常強大的工具,尤其是在報表統計等場景領域。它們不僅能夠簡化復雜的數據計算和分析,還能提高查詢效率和靈活性。窗口函數就像是數據庫操作中最鋒利的瑞士軍刀,為我們提供了一種強大而精確的方式來處理數據。
擴展鏈接:
Spring Boot框架下實現Excel服務端導入導出
項目實戰:在線報價采購系統(React +SpreadJS+Echarts)
Svelte 框架結合 SpreadJS 實現純前端類 Excel 在線報表設計
Copyright @ 2015-2022 中南網版權所有 關于我們 備案號: 浙ICP備2022016517號-4 聯系郵箱:514 676 113@qq.com