mysql 窗口函数_窗口函数到底有多神奇?

由于某些不可抗力,之前的几篇文章做了删除,重新上架,希望于你有益。

忙里偷闲。 我得承认,我写了将近小半个月的HQL。主要目的是做报表开发,但由于此报表背后牵扯的表实在太多,以至于我不得不使用xmind来梳理这些表的上下游关系,生怕出一点差错。这些表背后的语句大都只涉及到表连接,去重,简单运算,因许久未用到过窗口函数了,我不禁产生怀疑,这还是我面试的时候经常考察到的SQL吗? 实习和秋招笔面试的时候,SQL的考察必不可少,除了题目中会涉及业务背景外,大同小异的,大都考察聚合、表连接、窗口函数,尤以各种各样的窗口函数为重。 可不要再傻乎乎的问我,MySQL没有窗口函数啊,我怎么从没有看到过?在哪里能学到呢?盆友!清醒一点!多接触点其他的DBMS吧!几乎处处可见窗口函数,而且会频繁考察。 MySQL升级到8.0以上就能拥有此功能了,一般的窗口函数都能用,但是狗血的是我不能在上面试验grouping sets,只能在hive上写的时候才能“大展拳脚”,夸张了,hhhh,那么一起来看几道与窗口函数相关的题目吧。 题目一 表mall_rate中记录了不同商户的费率变化信息,要求 按照时间轴顺序,取出费率发生了状态变化的数据行 。表及相关数据如下: 78d1cc05166eba47552aada78f2c3501.png 53c0a0ba009763c8a3302bdfdd17518b.png 解题思路:lag或lead函数可以将上一行或下一行的字段内容获取到本行,这样便可以进行某些字段是否发生变化的比较,从而进行状态是否变化的比较,有些题目中会出现一些如“连续记录”,“沿时间轴”,“查询**上次记录的时间”,“查询**前n次记录的时间”等字眼,这些关键字预示着可能会需要用到lag或lead函数去获取上n行或下n行字段的内容到本行,进行数据选取或比较。

法1:

c603063a8a2c66d9cda9b5bfdcfe468c.png 查询结果如下: 869fbec116473487cef292bb3f2e78a4.png

法2:

8be51a7ec505b8f319762116a5048630.png 查询结果如下: 565a7320551a6ff11b2f0da6d2917864.png 知识点归纳:LAG(col,n,default)用于统计窗口内 往上第n行值,第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为null时,取默认值,如不指定,则为null) 66e44315766458dd727749ebe36dbb38.png 3464134c8d67e83cdcbffec476f00b44.png

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

5eafd55a7254e190c629b5fe385ac0b6.png f66e063073e33b213e9d6b2a42f44ea7.png

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

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

26955350d4435818a62f4fc35840efd5.png 240a9123ac5b835c3170018562ad626d.png

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

238888f6ab6f296ed93cd16dd8f3de1e.png b74cecc85be238ebd957652e820d9154.png

安排一道练习题吧~

992b259862f48bf512c9a00e9b8edee2.png

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

38648eac384aad34e2d456c8dc97bbd4.png 题目二

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

169cb0af488831b8da3a593226fbcd8e.png

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

解题思路:

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

法1:

e0f8508a1474e686610efa4347ae1ab0.png

法2:

45279b15bd34934dcf5ff8b4c5476e26.png

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

解题思路:

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

3e14e6701680a3a85a7b34e391953117.png

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

e1197fb8a45268e23a33ee5f44d33421.png

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

33beaa15e1e06bdfa27ec5ed7bdac757.png

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

解题思路:

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

解法如下:

ea1320407d06039b0333d7db6e3e5674.png

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

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

e0bba2a1f676842dfaf18485be5157a7.png 五月是个令人忙翻天的五月,我的公众号更新也变得不那么规律了。谢谢关注我的小可爱还一直在,希望你们之后求职的求职顺利,工作的工作顺利,还有......一切都好。 最近准备上一个分享板块,一方面是为明年实习的同学做经验及知识储备,另一方面为即将到来的秋招做经验分享和知识储备。已经预约了几位同学的经验分享了,因为时间不充足,还没来得及跟圈子里的同学挨个联系,希望想要进行分享,给别人带来一丢丢影响的同学,抓紧后台联系我呀~之后可以搞个小抽奖,福利放送什么的!感谢大家的分享和付出,比心。 整理的数据分析的一些SQL题目和笔面经整理,私信公众号,回复关键字“数分笔面经”。 喜欢的朋友记得点点 关注在看 吖~ 让更多的人发现我长胖吧! end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值