最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入解析MySQL的窗口函數(shù)

 更新時間:2023年07月14日 09:56:46   作者:打工人戶戶  
這篇文章主要介紹了深入解析MySQL的窗口函數(shù),窗口可以理解為記錄集合,窗口函數(shù)就是在滿足某種條件的記錄集合上執(zhí)行的特殊函數(shù),即:應用在窗口內(nèi)的函數(shù),需要的朋友可以參考下

對一個成熟的數(shù)據(jù)分析師來說,窗口函數(shù)可以大幅提高查詢效率,且SQL代碼優(yōu)雅。

img

一、定義

窗口可以理解為記錄集合,窗口函數(shù)就是在滿足某種條件的記錄集合上執(zhí)行的特殊函數(shù)。 即:應用在窗口內(nèi)的函數(shù)。

靜態(tài)窗口:每條記錄都要在此窗口內(nèi)執(zhí)行函數(shù),窗口大小都是固定的。

動態(tài)窗口:不同的記錄對應著不同的窗口,這種動態(tài)變化的窗口叫滑動窗口。

二、語法格式

函數(shù)名(字段名) over(子句) 

over()括號內(nèi)若不寫,則意味著窗口函數(shù)基于滿足where條件的所有行進行計算。

若括號內(nèi)不為空,則支持以下語法來設置窗口。

函數(shù)名(字段名) over(partition by <要分列的組> order by <要排序的列> rows between <數(shù)據(jù)范圍>) 

數(shù)據(jù)范圍:

rows between 2 preceding and current row # 取本行和前面兩行
rows between unbounded preceding and current row # 取本行和之前所有的行 
rows between current row and unbounded following # 取本行和之后所有的行 
rows between 3 preceding and 1 following # 從前面三行和下面一行,總共五行 
# 當order by后面沒有rows between時,窗口規(guī)范默認是取本行和之前所有的行
# 當order by和rows between都沒有時,窗口規(guī)范默認是分組下所有行(rows between unbounded preceding and unbounded following) 

三、分類

1、聚合類

聚合窗口函數(shù)與普通聚合函數(shù)的區(qū)別

  • 普通場景下的聚合函數(shù)是將多條記錄聚合為一條**(多到一);**窗口函數(shù)是每條記錄都會執(zhí)行,有幾條記錄執(zhí)行完還是幾條**(多到多)**。
  • 接下來通過解決具體需求來讓大家更加了解窗口函數(shù)的用法,希望大家閱讀完能動手練習。 先創(chuàng)建user_trade表:
-- 現(xiàn)有2018~2020某電商平臺訂單信息表user_trade
create table user_trade (
 user_name  varchar(20) COMMENT '用戶名',
 piece  int COMMENT '購買數(shù)量',
 price  double COMMENT '價格',
 pay_amount double COMMENT '支付金額',
 goods_category varchar(20) COMMENT '商品品類',
 pay_time date COMMENT '支付日期'
);

從navicat中導入以下數(shù)據(jù)源:

user_trade數(shù)據(jù)源:https://gitee.com/hu-weiqing/datasource/blob/master/user_trade.xlsx

數(shù)據(jù)隨機展示10條如下:

  • 累計求和:sum()over()
-- 需求1: 查詢出2019年每月的支付總額和當年累積支付總額 
select a.mon,a.pay_amount,sum(a.pay_amount) over(order by a.mon) as sum_amount
from(
select month(a.pay_time) as mon,sum(a.pay_amount) as pay_amount
from user_trade a
where year(a.pay_time) = '2019'
group by month(a.pay_time)
) a ;
-- 需求2:查詢出2018-2019年每月的支付總額和當年累積支付總額
select a.*,sum(a.pay_amount) over(partition by a.year order by a.mon) as sum_amount
from(
select year(a.pay_time) as year,month(a.pay_time) as mon,sum(a.pay_amount) as pay_amount
from user_trade a
where year(a.pay_time) in('2018','2019')
group by year(a.pay_time),month(a.pay_time)
) a ;

img

需求1運行結(jié)果(部分)

img

需求2運行結(jié)果(部分)

  • 移動平均:avg() over()
-- 需求3: 查詢出2019年每個月的近三月移動平均支付金額
select a.mon,a.pay_amount,
avg(a.pay_amount) over(order by a.mon rows between 2 preceding and current row) as avg_amount
from(
select month(a.pay_time) as mon,sum(a.pay_amount) as pay_amount
from user_trade a
where year(a.pay_time) = '2019'
group by month(a.pay_time)
) a ;

img

需求3運行結(jié)果(部分)

  • 最大/最小值:max()/min() over()
-- 需求4: 查詢出每四個月的最大月總支付金額
select 
a.mon,
a.pay_amount,
max(a.pay_amount) over(order by a.mon rows between 3 preceding and current row) as max_amount
from(
select SUBSTRING(a.pay_time,1,7) as mon,sum(a.pay_amount) as pay_amount
from user_trade a
group by SUBSTRING(a.pay_time,1,7)
)a ;

img

需求4運行結(jié)果(部分)

2、排序類

  • row_number()、rank() 和dense_rank()
-- 需求4: 查詢出每四個月的最大月總支付金額
select 
a.mon,
a.pay_amount,
max(a.pay_amount) over(order by a.mon rows between 3 preceding and current row) as max_amount
from(
select SUBSTRING(a.pay_time,1,7) as mon,sum(a.pay_amount) as pay_amount
from user_trade a
group by SUBSTRING(a.pay_time,1,7)
)a ;

img

需求5運行結(jié)果(部分)

row_number()、rank() 和dense_rank() 三種排序函數(shù)的區(qū)別:

row_number:每一行記錄生成一個序號,依次排序且不會重復。 12345…

rank:跳躍排序,生成的序號有可能不連續(xù)。11345…

dense_rank:在生成序號時是連續(xù)的。11234…

  • ntile(n)over()

ntile(n)用于將分組數(shù)據(jù)按照順序切分成n片,返回當前切片值. n表示切片的數(shù)量; 不支持rows between

-- 需求6: 查詢出將2020年2月的支付用戶,按照支付金額分成5組后的結(jié)果
select 
a.user_name,
sum(a.pay_amount) as pay_amount,
ntile(5) over(order by sum(a.pay_amount) desc) as level
from user_trade a
where SUBSTRING(a.pay_time,1,7) = '2020-02'
group by a.user_name;
-- 需求7: 查詢出2020年支付金額排名前30%的所有用戶
select a.user_name,a.pay_amount
from (
select 
a.user_name,
sum(a.pay_amount) as pay_amount,
ntile(10) over(order by sum(a.pay_amount) desc) as level
from user_trade a
where year(a.pay_time) = '2020'
group by a.user_name
) a 
where a.level in(1,2,3);

img

需求6運行結(jié)果(部分)

img

需求7運行結(jié)果(部分)

3、偏移分析函數(shù)

  • lag() over()向上偏移

lag(exp_str,offset,defval) exp_str:字段名 offset:偏移量 defval:默認值。當向上偏移了offset行已經(jīng)超出了表的范圍時,lag()函數(shù)將defval這個參數(shù)值作為函數(shù)的返回值,若沒有指定默認值,則返回NULL。

-- 需求8: 查詢出King和West的時間偏移(前N行)
select a.user_name,a.pay_time,
lag(a.pay_time,1,a.pay_time) over(partition by a.user_name order by a.pay_time) as lag1,
-- 沒有傳入偏移量,那么默認就是1,找不到的話,此處也沒有給默認值,為null
lag(a.pay_time) over(partition by a.user_name order by a.pay_time) as lag2,
lag(a.pay_time,2,a.pay_time) over(partition by a.user_name order by a.pay_time) as lag3,
lag(a.pay_time,2) over(partition by a.user_name order by a.pay_time) as lag4
from user_trade a 
where a.user_name in('King','West');

img

需求8運行結(jié)果

  • lead() over()向下偏移

用法同lag()over()函數(shù)。

補充練習:

-- 需求9: 查詢出支付時間間隔超過100天的用戶數(shù)
select count(distinct a.user_name)
from (
select a.user_name,a.pay_time,
lag(a.pay_time) over(partition by a.user_name order by a.pay_time) as lg
from user_trade a 
) a 
where DATEDIFF(a.pay_time,a.lg) >100;
# 需求9運行結(jié)果為180
-- 需求10: 查詢出每年支付時間間隔最長的用戶
select c.years,c.user_name,c.pay_days 
from(
select b.years,b.user_name,datediff(b.pay_time,b.lg) as pay_days,
rank() over(partition by b.years order by datediff(b.pay_time,b.lg) desc) as rk 
from (
select year(a.pay_time) as years,a.user_name,a.pay_time,
lag(a.pay_time) over(partition by a.user_name,year(a.pay_time) order by a.pay_time) as lg
from user_trade a 
) b 
where b.lg is not null
) c 
where c.rk = 1;

img

需求10運行結(jié)果

窗口函數(shù)在數(shù)據(jù)分析師的工作中應用非常廣,如果不會窗口函數(shù),很可能同樣的需求用普通表關聯(lián)寫需要關聯(lián)很多張表,導致性能不好,查詢速度非常慢。

到此這篇關于深入解析MySQL的窗口函數(shù)的文章就介紹到這了,更多相關MySQL窗口函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MySQL中DROP、DELETE與TRUNCATE的對比分析

    MySQL中DROP、DELETE與TRUNCATE的對比分析

    在MySQL數(shù)據(jù)庫操作中,DROP、DELETE和TRUNCATE是三個常用的數(shù)據(jù)操作命令,本文將從多個維度對這三個命令進行詳細對比和解析,幫助讀者更好地掌握它們的應用,感興趣的朋友一起看看吧
    2025-07-07
  • MySQL?Workbench操作圖文詳解(史上最細)

    MySQL?Workbench操作圖文詳解(史上最細)

    Workbench是MySQL最近釋放的可視數(shù)據(jù)庫設計工具,這個工具是設計 MySQL數(shù)據(jù)庫的專用工具,下面這篇文章主要給大家介紹了關于MySQL?Workbench操作的相關資料,需要的朋友可以參考下
    2023-03-03
  • mysql 數(shù)據(jù)同步 出現(xiàn)Slave_IO_Running:No問題的解決方法小結(jié)

    mysql 數(shù)據(jù)同步 出現(xiàn)Slave_IO_Running:No問題的解決方法小結(jié)

    mysql replication 中slave機器上有兩個關鍵的進程,死一個都不行,一個是slave_sql_running,一個是Slave_IO_Running,一個負責與主機的io通信,一個負責自己的slave mysql進程。
    2011-05-05
  • MySQL導入導出.sql文件及常用命令小結(jié)

    MySQL導入導出.sql文件及常用命令小結(jié)

    在MySQL Qurey Brower中直接導入*.sql腳本,是不能一次執(zhí)行多條sql命令的,下面為大家介紹下MySQL導入導出.sql文件及常用命令
    2014-08-08
  • MySQL?UPDATE多表關聯(lián)更新的實現(xiàn)示例

    MySQL?UPDATE多表關聯(lián)更新的實現(xiàn)示例

    MySQL可以基于多表查詢更新數(shù)據(jù),本文主要介紹了MySQL?UPDATE多表關聯(lián)更新的實現(xiàn)示例,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • MySQL DQL語句的具體使用

    MySQL DQL語句的具體使用

    本文主要介紹了MySQL DQL語句的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • MySql索引提高查詢速度常用方法代碼示例

    MySql索引提高查詢速度常用方法代碼示例

    這篇文章主要介紹了MySql索引提高查詢速度常用方法代碼示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • 分析MySQL復制以及調(diào)優(yōu)原理和方法

    分析MySQL復制以及調(diào)優(yōu)原理和方法

    本篇文章給大家詳細分析了MySQL復制以及調(diào)優(yōu)原理和方法,并通過代碼詳細分析了具體操作,有需要的朋友參考下吧。
    2018-01-01
  • CentOS7環(huán)境安裝包部署并配置MySQL5.7教程

    CentOS7環(huán)境安裝包部署并配置MySQL5.7教程

    文章詳細介紹了卸載和重新安裝MySQL 5.7的步驟,包括卸載舊版本、查看和卸載相關服務、下載和解壓新版本安裝包、創(chuàng)建用戶和目錄、配置my.cnf、初始化數(shù)據(jù)庫、啟動和修改密碼等過程,同時,還解決了客戶端不支持問題以及配置遠程登錄的步驟
    2026-02-02
  • mysql實現(xiàn)按組區(qū)分后獲取每組前幾名的sql寫法

    mysql實現(xiàn)按組區(qū)分后獲取每組前幾名的sql寫法

    這篇文章主要介紹了mysql實現(xiàn)按組區(qū)分后獲取每組前幾名的sql寫法,具有很好的參考價值,希望對大家有所幫助。
    2023-03-03

最新評論

广河县| 宣武区| 萨嘎县| 漳平市| 分宜县| 东乡| 盘山县| 绥阳县| 固阳县| 桃源县| 海盐县| 静乐县| 东港市| 固始县| 大方县| 昌宁县| 体育| 新丰县| 中西区| 张家口市| 迭部县| 云南省| 尖扎县| 凤翔县| 龙陵县| 灵台县| 彭水| 潞城市| 南投县| 新宾| 鲁甸县| 淮北市| 扎鲁特旗| 龙泉市| 额敏县| 鄱阳县| 西乌珠穆沁旗| 桐城市| 新营市| 磴口县| 枝江市|