SQL SEVER 開窗函數總結
作為一名剛剛入門的開發人員,要學的東西很多很多,有些無從下手。秉著“問題是病、技術是藥、對癥下藥”的原則,將工作中遇到的問題所需的技術進行梳理、歸納和總結。
一、什麽是開窗函數
首先,什麽是開窗函數,與聚合函數一樣,開窗函數也是對行集組進行聚合計算,但是它不像普通聚合函數那樣每組只返回一個值,開窗函數可以為每組返回多個值,因為開窗函數所執行聚合計算的行集組是窗口(這裏的窗口是指運算將要操作的行的集合)。在開窗函數出現之前存在著很多用 SQL 語句很難解決的問題,很多都要通過復雜的相關子查詢或者存儲過程來完成。下面舉例說明:
現在有這樣的要求:查詢成績在90分以下的學生信息,並在每行顯示低於90分的學生總數。
通過使用子查詢我們可以得出查詢結果,代碼如下:
SELECT NAME , AGE , SCORES , ( SELECT COUNT(NAME) FROM Table_1 WHERE SCORES < 90 ) FROM Table_1 WHERE SCORES < 90;View Code
雖然使用子查詢能夠解決這個問題,但是當數據結構很復雜時,子查詢的使用非常麻煩,使用開窗函數則大大簡化了查詢邏輯,以下代碼將展示使用開窗函數得到同樣的查詢結果:
SELECT NAME , AGE , SCORES , COUNT(NAME) OVER ( ) FROM Table_1 WHERE SCORES < 90;View Code
通過以上例子,我們可以看到使用開窗函數可以解決一些需要通過復雜的相關子查詢或者存儲過程來實現的查詢。與聚合函數不同的是,開窗函數在聚合函數後增加了一個OVER關鍵字。
開窗函數的調用格式為:函數名(列) OVER(選項) OVER 關鍵字表示把函數當成開窗函數而不是聚合函數。SQL 標準允許將所有聚合函數用做開窗函數,使用OVER 關鍵字來區分這兩種用法。
二、開窗函數分類
開窗函數可分為:聚合開窗函數和排序開窗函數兩種
2.1 聚合開窗函數
在上述例子中,我們所使用的就是聚合開窗函數。OVER關鍵字後的括號中可以為空,也可以使用 PARTITION BY 子句來定義行的分區來供進行聚合計算。下面的SQL語句使用“AGE”進行分區, 用於查詢學生的年齡分布以及相同年齡的學生的個數。
SELECT DISTINCT
AGE ,
COUNT(NAME) OVER ( PARTITION BY AGE )
FROM Table_1;
View Code
2.2 排序開窗函數
使用較為頻繁的排序開窗函數有:ROW_NUMBER(行號)、RANK(排名)、DENSE_RANK(密集排名)和NTILE(分組排名)。
還是上面的例子,現提出如下要求:查詢成績排名第2的學生信息。這裏我們就可以使用ROW_NUMBER(行號)函數來實現查詢目的。代碼如下:
SELECT * FROM ( SELECT NAME , AGE , SCORES , ROW_NUMBER() OVER ( ORDER BY SCORES DESC ) AS rownum FROM Table_1 ) T WHERE T.rownum = 2;View Code
其他排序開窗函數原理與ROW_NUMBER類似,根據不同需求選擇使用哪種開窗函數。但是需要註意一點的是,在排序開窗函數中使用PARTITION BY子句需要放置在ORDER BY子句之前。
三、總結
本文對開窗函數進行了簡要介紹,並對如何使用開窗函數進行了說明。正確的使用開窗函數可以有效的提高查詢效率,優化查詢邏輯,但就像開篇提到的“問題是病、技術是藥、對癥下藥”,只有針對合適的問題使用合適的技術,才能事半功倍。
SQL SEVER 開窗函數總結