SQL窗口函數(shù)之排名窗口函數(shù)的使用
關(guān)于窗口函數(shù)的基礎(chǔ),請看文章SQL窗口函數(shù)
取值窗口函數(shù)可以用于返回窗口內(nèi)指定位置的數(shù)據(jù)行。常見的取值窗口函數(shù)如下:
LAG函數(shù)可以返回窗口內(nèi)當(dāng)前行之前的第N行數(shù)據(jù)。LEAD函數(shù)可以返回窗口內(nèi)當(dāng)前行之后的第N行數(shù)據(jù)。FIRST_VALUE函數(shù)可以返回窗口內(nèi)第一行數(shù)據(jù)。LAST_VALUE函數(shù)可以返回窗口內(nèi)最后一行數(shù)據(jù)。NTH_VALUE函數(shù)可以返回窗口內(nèi)第N行數(shù)據(jù)。
其中,LAG函數(shù)和LEAD函數(shù)不支持動態(tài)的窗口大小,它們以整個分區(qū)作為分析的窗口。
案例分析
案例使用的示例表
下面的查詢中會用到一張表,sales_monthly表中存儲了商品銷量信息,product表示產(chǎn)品名稱,ym表示年月,amount表示銷售金額(元)。
以下是該表中的部分?jǐn)?shù)據(jù):
這個表的初始化腳本可以在文章底部獲取。
1.環(huán)比分析
環(huán)比增長指的是本期數(shù)據(jù)與上期數(shù)據(jù)相比的增長,例如,產(chǎn)品2019年6月的銷售額與2019年5月的銷售額相比增加的部分。
以下語句統(tǒng)計了各種產(chǎn)品每個月的環(huán)比增長率:
SELECT s.product AS "產(chǎn)品", s.ym AS "年月", s.amount AS "銷售額", ( (s.amount - LAG(s.amount,1) OVER (PARTITION BY product ORDER BY s.ym))/ LAG(s.amount,1) OVER (PARTITION BY product ORDER BY s.ym) ) * 100 AS "環(huán)比增長率(%)" FROM sales_monthly s ORDER BY s.product,s.ym
其中,LAG(amount,1)表示獲取上一期的銷售額,PARTITION BY選項表示按照產(chǎn)品分區(qū),ORDER BY選項表示按照月份進(jìn)行排序。
當(dāng)前月份的銷售額amount減去上一期的銷售額,再除以上一期的銷售額,就是環(huán)比增長率。
該查詢返回的結(jié)果如下:
2018年1月是第一期,因此其環(huán)比增長率為空。
“桔子”2018年2月的環(huán)比增長率約為0.2856%((10183-10154)/10154×100),依此類推。
2.同比分析
同比增長指的是本期數(shù)據(jù)與上一年度或歷史同期相比的增長,例如,產(chǎn)品2019年6月的銷售額與2018年6月的銷售額相比增加的部分。
以下語句統(tǒng)計了各種產(chǎn)品每個月的同比增長率:
SELECT s.product AS "產(chǎn)品", s.ym AS "年月", s.amount AS "銷售額", ( (s.amount - LAG(s.amount,12) OVER (PARTITION BY product ORDER BY s.ym))/ LAG(s.amount,12) OVER (PARTITION BY product ORDER BY s.ym) ) * 100 AS "同比增長率(%)" FROM sales_monthly s ORDER BY s.product,s.ym
其中,LAG(amount,12)表示當(dāng)前月份之前第12期的銷售額,也就是去年同月份的銷售額。
PARTITION BY選項表示按照產(chǎn)品分區(qū),ORDER BY選項表示按照月份進(jìn)行排序。
當(dāng)前月份的銷售額amount減去去年同期的銷售額,再除以去年同期的銷售額,就是同比增長率。
該查詢返回的結(jié)果如下:
2018年的12期數(shù)據(jù)都沒有對應(yīng)的同比增長率,“桔子”2019年1月的同比增長率約為9.3067%((11099-10154)/10154×100),依此類推。
提示:LEAD函數(shù)與LAG函數(shù)的使用方法類似,不過它的返回結(jié)果是當(dāng)前行之后的第N行數(shù)據(jù)。
3.復(fù)合增長率
復(fù)合增長率是第N期的數(shù)據(jù)除以第一期的基準(zhǔn)數(shù)據(jù),然后開N-1次方再減去1得到的結(jié)果。
假如2018年的產(chǎn)品銷售額為10000,2019年的產(chǎn)品銷售額為12500,2020年的產(chǎn)品銷售額為15000。那么這兩年的復(fù)合增長率的計算方式如下:
以年度為單位計算的復(fù)合增長率被稱為年均復(fù)合增長率,以月度為單位計算的復(fù)合增長率被稱為月均復(fù)合增長率。
以下查詢統(tǒng)計了自2018年1月以來不同產(chǎn)品的月均銷售額復(fù)合增長率:
WITH s (product,ym,amount,first_amount,num) AS ( SELECT m.product, m.ym, m.amount, FIRST_VALUE(m.amount) OVER (PARTITION BY m.product ORDER BY m.ym), ROW_NUMBER() OVER (PARTITION BY m.product ORDER BY m.ym) FROM sales_monthly m ) SELECT product AS "產(chǎn)品", ym AS "年月",amount AS "銷售額", (POWER( amount/first_amount, 1.0/NULLIF(num-1,0)) -1)*100 AS "月均復(fù)合增長率(%)" FROM s ORDER BY product, ym
首先定義了一個通用表表達(dá)式,其中FIRST_VALUE(amount)返回了第一期(201801)的銷售額,ROW_NUMBER函數(shù)返回了每一期的編號。
主查詢中的POWER函數(shù)用于執(zhí)行開方運(yùn)算,NULLIF函數(shù)用于處理第一期數(shù)據(jù)的除零錯誤,常量1.0用于避免由整數(shù)除法所導(dǎo)致的精度丟失問題。
該查詢返回的結(jié)果如下:
2018年1月是第一期,因此其產(chǎn)品月均銷售額復(fù)合增長率為空。
“桔子”2018年2月的月均銷售額復(fù)合增長率等于它的環(huán)比增長率,2018年3月的月均銷售額復(fù)合增長率等于0.4471%,依此類推。
4.不同產(chǎn)品最高和最低銷售額
以下語句統(tǒng)計了不同產(chǎn)品最低銷售額、最高銷售額以及第三高銷售額所在的月份:
SELECT product AS "產(chǎn)品", ym AS "年月",amount AS "銷售額", FIRST_VALUE(m.ym) OVER ( PARTITION BY m.product ORDER BY m.amount DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS "最高銷售額月份", LAST_VALUE(m.ym) OVER ( PARTITION BY m.product ORDER BY m.amount DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS "最低銷售額月份", NTH_VALUE(m.ym,3) OVER ( PARTITION BY m.product ORDER BY m.amount DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS "第三高銷售額月份" FROM sales_monthly m ORDER BY product, ym;
三個窗口函數(shù)的OVER子句相同,PARTITION BY選項表示按照產(chǎn)品進(jìn)行分區(qū),ORDER BY選項表示按照銷售額從高到低排序。
以上三個函數(shù)的默認(rèn)窗口都是從分區(qū)的第一行到當(dāng)前行,因此我們將窗口擴(kuò)展到了整個分區(qū)。
該查詢返回的結(jié)果如下:
“桔子”的最高銷售額出現(xiàn)在2019年6月,最低銷售額出現(xiàn)在2018年1月,第三高銷售額出現(xiàn)在2019年4月。
示例表和腳本
-- 創(chuàng)建銷量表sales_monthly -- product表示產(chǎn)品名稱,ym表示年月,amount表示銷售金額(元) CREATE TABLE sales_monthly(product VARCHAR(20), ym VARCHAR(10), amount NUMERIC(10, 2)); -- 生成測試數(shù)據(jù) INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201801',10159.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201802',10211.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201803',10247.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201804',10376.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201805',10400.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201806',10565.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201807',10613.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201808',10696.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201809',10751.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201810',10842.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201811',10900.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201812',10972.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201901',11155.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201902',11202.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201903',11260.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201904',11341.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201905',11459.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('蘋果','201906',11560.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201801',10138.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201802',10194.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201803',10328.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201804',10322.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201805',10481.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201806',10502.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201807',10589.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201808',10681.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201809',10798.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201810',10829.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201811',10913.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201812',11056.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201901',11161.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201902',11173.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201903',11288.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201904',11408.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201905',11469.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201906',11528.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201801',10154.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201802',10183.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201803',10245.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201804',10325.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201805',10465.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201806',10505.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201807',10578.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201808',10680.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201809',10788.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201810',10838.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201811',10942.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201812',10988.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201901',11099.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201902',11181.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201903',11302.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201904',11327.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201905',11423.00); INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201906',11524.00);
到此這篇關(guān)于SQL窗口函數(shù)之排名窗口函數(shù)的使用的文章就介紹到這了,更多相關(guān)SQL 排名窗口函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL Server如何通過創(chuàng)建臨時表遍歷更新數(shù)據(jù)詳解
這篇文章主要給大家介紹了關(guān)于SQL Server如何通過創(chuàng)建臨時表遍歷更新數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09SQL?Server日期時間字符串的處理和轉(zhuǎn)換方法詳解
這篇文章主要給大家介紹了關(guān)于SQL?Server日期時間字符串的處理和轉(zhuǎn)換方法,在sql server數(shù)據(jù)庫中,日期時間類型經(jīng)常要轉(zhuǎn)換成字符串類型使用,并且格式也根據(jù)需要而不同,需要的朋友可以參考下2023-08-08數(shù)據(jù)庫高并發(fā)情況下重復(fù)值寫入的避免 字段組合約束
10線程同時操作,頻繁出現(xiàn)插入同樣數(shù)據(jù)的問題的解決方法。大家可以參考下。2009-08-08Sql?Prompt?10下載與安裝破解圖文教程(最新推薦)
sql?prompt?10是一款擁有智能提示功能的SQL?Server和VS插件,,特別適合開發(fā)者不大熟悉腳本時候使用,這篇文章主要介紹了Sql?Prompt?10下載與安裝破解圖文教程,需要的朋友可以參考下2023-03-03SQL Server 2012 FileTable 新特性詳解
FileTable是基于FILESTREAM的一個特性。本文給大家介紹SQL Server 2012 FileTable 新特性詳解,非常不錯,感興趣的朋友一起學(xué)習(xí)吧2016-08-08sqlserver 各種判斷是否存在(表名、函數(shù)、存儲過程等)
在sql server中,如何判斷sql server表是否存在呢?下面就將為您詳細(xì)介紹該方法,供您參考,希望對您加深理解sql server表能起到些許作用2013-02-02SQLServer 數(shù)據(jù)庫中如何保持?jǐn)?shù)據(jù)一致性
復(fù)制是SQLServer數(shù)據(jù)庫中保持?jǐn)?shù)據(jù)一致性的一種手段。2009-06-06SQL?server常見的數(shù)據(jù)類型轉(zhuǎn)換整理大全
這篇文章主要給大家介紹了關(guān)于SQL?server常見的數(shù)據(jù)類型轉(zhuǎn)換整理的相關(guān)資料,在 SQL Server中可以使用CAST或CONVERT函數(shù)來進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換,需要的朋友可以參考下2023-11-11