PostgreSQL 高级SQL(四) 滑动窗口函数

        上章节我们讲述的窗口函数都属于静态窗口,然而我们很多场景是需要滑动窗口,比如我们需要查看这样的一张报表,这张报表包含国家名字,年份,GDP,当前年份与去年和面的GDP均值,也就是说GDP均值这一列随着行数的推移,动态移动变化的,那么我们可以借助PG的滑动窗口来完成这个功能,SQL如下,

select country_name,"year",gdp,avg(gdp) over(partition by country_name order by "year" desc rows between 1 preceding and 1 following) from country_gdp_year_final ff 

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017;

获取每年与前后俩年的均值GDP

preceding 中文意思:前面的

following  中文意思 :后面的

上面的 rows between 1 preceding and 1 following 定义的滑动窗口包含三行,当前行,当前行的前一行,当前行的后一行

我们可以计算一下每行的平均值的意义,首先我们的窗口限制在国家这个字段窗口里面,并且按照年份降序排序,

中国2017年avg(gdp)=(2017GDP+2016GDP)/2 因为没有选择2018年所以2017年的前一年是不存在的,后一年是2016年

中国2016年avg(gdp)=(2017GDP+2016GDP+2015GDP)/3 2016年是当前年份

中国2015年avg(gdp)=(2016GDP+2015GDP+2014GDP)/3 2015年是当前年份

......

中国2012年avg(gdp)=(2013GDP+2012GDP)/2 2012年是当前年份,因为没有选择2011年,所以2012年的后一年不存在,前一年是2013

        我们可以通过列转行函数array_agg来进行一下更加直观的认识

select country_name,"year",gdp,array_agg(gdp) over(partition by country_name order by "year" desc rows between 1 preceding and 1 following) from country_gdp_year_final ff

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017;

行转列直观感受

PG里面的滑动窗口还有一个关键词:unbounded(无届的),这个关键词可以放在preceding ,following之前,

select country_name,"year",gdp,array_agg("year") over(partition by country_name order by "year" desc rows between unbounded preceding and 1 following) from country_gdp_year_final

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017;

总结:从上面的示例中我们可以看出滑动窗口函数的强大,但是需要记住的一点是:移动窗口需要配合order by子句一起使用,如果没有order by的话,就会出现问题,因为数据没有事先排序,那么滑动窗口计算出来的数据就会出出现随机,我们可以将order by 子句去掉来看一下结果

select country_name,"year",gdp,array_agg("year") over(partition by country_name rows between 1 preceding and 1 following) from country_gdp_year_final

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017;

没有order by 子句的滑动窗口结果

 如果我们想要获取的不仅仅是平均值还有最大值和最小值这俩列,我们可以这样使用

select country_name,"year",gdp,avg(gdp) over(partition by country_name order by "year" desc),

min(gdp) over(partition by country_name order by "year" desc ),

max(gdp) over(partition by country_name order by "year" desc)

from country_gdp_year_final

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017;


我们看一下上面的SQL代码,可以看到 over()括号里的代码都是一样的,在此,PG为我们提供一个提取窗口子句的功能,我们可以将上面的代码转换为下面等价可读性更好的代码

select country_name,"year",gdp,avg(gdp) over(myWindows),

min(gdp) over(myWindows),

max(gdp) over(myWindows)

from country_gdp_year_final 

where country_code in('CHN','JPN','USA','DEU','CAN','FRA') and "year" between 2012 and 2017

window myWindows as(partition by country_name order by "year" desc);

window提取子窗口

可以看到使用window提取子句后的代码可读性更好,但是使用window的时候,上面的滑动窗口是不可以使用window提取子句的,目前PG不支持

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容