窗口函数到底有多「神奇」?

 窗口函数到底有多「神奇」?_第1张图片

忙里偷闲。

我得承认,我写了将近小半个月的HQL。主要目的是做报表开发,但由于此报表背后牵扯的表实在太多,以至于我不得不使用xmind来梳理这些表的上下游关系,生怕出一点差错。这些表背后的语句大都只涉及到表连接,去重,简单运算,因许久未用到过窗口函数了,我不禁产生怀疑,这还是我面试的时候经常考察到的SQL吗?

实习和秋招笔面试的时候,SQL的考察必不可少,除了题目中会涉及业务背景外,大同小异的,大都考察聚合、表连接、窗口函数,尤以各种各样的窗口函数为重。

可不要再傻乎乎的问我,MySQL没有窗口函数啊,我怎么从没有看到过?在哪里能学到呢?盆友!清醒一点!多接触点其他的DBMS吧!几乎处处可见窗口函数,而且会频繁考察。

MySQL升级到8.0以上就能拥有此功能了,一般的窗口函数都能用,但是狗血的是我不能在上面试验grouping sets,只能在hive上写的时候才能“大展拳脚”,夸张了,hhhh,那么一起来看几道与窗口函数相关的题目吧。

空白

题目一

输入

表mall_rate中记录了不同商户的费率变化信息,要求按照时间轴顺序,取出费率发生了状态变化的数据行。表及相关数据如下:

窗口函数到底有多「神奇」?_第2张图片

窗口函数到底有多「神奇」?_第3张图片

解题思路:

lag或lead函数可以将上一行或下一行的字段内容获取到本行,这样便可以进行某些字段是否发生变化的比较,从而进行状态是否变化的比较,有些题目中会出现一些如“连续记录”,“沿时间轴”,“查询**上次记录的时间”,“查询**前n次记录的时间”等字眼,这些关键字预示着可能会需要用到lag或lead函数去获取上n行或下n行字段的内容到本行,进行数据选取或比较。

法1:

窗口函数到底有多「神奇」?_第4张图片

查询结果如下:

窗口函数到底有多「神奇」?_第5张图片

法2:

窗口函数到底有多「神奇」?_第6张图片

查询结果如下:

窗口函数到底有多「神奇」?_第7张图片

知识点归纳:

LAG(col,n,default)用于统计窗口内往上第n行值,第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为null时,取默认值,如不指定,则为null)

窗口函数到底有多「神奇」?_第8张图片

窗口函数到底有多「神奇」?_第9张图片

LEAD(col,n,default)与LAG相反,用于统计窗口内往下第n行值,第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为null时,取默认值,如不指定,则为null)

窗口函数到底有多「神奇」?_第10张图片

窗口函数到底有多「神奇」?_第11张图片

与LAG和LEAD同时作为知识点出现的,还有FIRST_VALUE和LAST_VALUE。

FIRST_VALUE(字段),取分组内排序后,截止到当前行的第一个值

窗口函数到底有多「神奇」?_第12张图片

窗口函数到底有多「神奇」?_第13张图片

LAST_VALUE(字段),取分组内排序后,截止到当前行的最后一个值

窗口函数到底有多「神奇」?_第14张图片

窗口函数到底有多「神奇」?_第15张图片

安排一道练习题吧~

窗口函数到底有多「神奇」?_第16张图片

表tmp中包括用户及其访问的场景及对应访问时间,求取用户id对应的前两个不同的场景(如果场景重复,选访问时间在前的场景,访问场景数不足两个时,输出到不足两个的输出即可),输出示例如下:

窗口函数到底有多「神奇」?_第17张图片

空白

题目二

输入

某商店有如下一张用户订单表order_table,其中记录了用户名,订单时间及订单金额,以此表为例,可以提出多个用窗口函数解决的小问题。相关数据如下:

窗口函数到底有多「神奇」?_第18张图片

(1)查询本店2017年1月份有购买行为的顾客姓名及购买次数。

解题思路:

可以采用一般的聚合函数count(),也可以使用窗口函数count() over();对于日期的限制可采用各种方式,如日期转换函数,也可以使用substr()。

法1:

窗口函数到底有多「神奇」?_第19张图片

法2:

窗口函数到底有多「神奇」?_第20张图片

(2)查询顾客的购买明细及每个月所有顾客的购买总额。

解题思路:

由于需要每位顾客明细后都要带一个当月所有顾客购买总额的字段,因此可以选择使用窗口函数中的sum() over()获得这个字段。

除此之外,也可以使用sum() over()做很多其他场景的操作,比如:

也可以使用先前介绍的lag或lead去求取顾客的上一次购买时间:

(3)查询整个订单信息中前20%时间的订单信息。

解题思路:

排序,取前20%。以前我有过一种操作是先使用窗口函数中的row_number()进行排序,搞一个rank,然后取最大rank的20%作为限制条件,取到前20%。后来发现别人都有顶好用的ntile,我真的是!!!

解法如下:

窗口函数到底有多「神奇」?_第21张图片

分桶(分组排序),按照你的意愿进行设置,分为几个桶,比如5个,每个桶占20%的记录,每个桶会有编号,取出想取的编号对应的数据即可。

其他各种各样有趣和有用的函数还有一箩筐,但是个人接触的也有限,正在慢慢学习中,以前分享的row_number,rank,dense_rank不知道你们还记不记得了,划重点呀!

我的「2020年PDD笔面经分享」

关于我印象比较深刻的grouping sets,cube, rollup就之后再分享啦~

窗口函数到底有多「神奇」?_第22张图片

五月是个令人忙翻天的五月,我的公众号更新也变得不那么规律了。谢谢关注我的小可爱还一直在,希望你们之后求职的求职顺利,工作的工作顺利,还有......一切都好。

最近准备上一个分享板块,一方面是为明年实习的同学做经验及知识储备,另一方面为即将到来的秋招做经验分享和知识储备。已经预约了几位同学的经验分享了,因为时间不充足,还没来得及跟圈子里的同学挨个联系,希望想要进行分享,给别人带来一丢丢影响的同学,抓紧后台联系我呀~之后可以搞个小抽奖,福利放送什么的!感谢大家的分享和付出,比心。

之前同学分享的两篇文章在这里,仅做参考。实际分享内容不限,可以是踩坑指南,可以是经验,可以是笔面经,等等等等,只要你愿意,后台为你敞开!

零数据分析实习经历如何秋招?

我拿到了网易严选数据分析暑期实习offer

北森测评题私信公众号,回复关键字“北森题库”。

整理的数据分析的一些SQL题目和笔面经整理,私信公众号,回复关键字“数分笔面经”。

喜欢的朋友记得点点关注在看吖~ 让更多的人发现我长胖吧!

end

你可能感兴趣的:(窗口函数到底有多「神奇」?)