大厂SQL面试必考点
一个数据工作者面试数据相关岗位,SQL查询语句是必不可少的笔试环节,本文记录大厂们的一些SQL常考面试题,主要还是涉及到窗口函数和case when的用法。!
SQL面试题
- 找出连续7天登陆,连续30天登陆的用户(小红书笔试,电信云面试),最大连续登陆天数的问题 --窗口函数
- 求连续点击三次的用户数,中间不能有别人的点击 ,最大连续天数的变形问题(腾讯微保面试)–窗口函数
- 计算除去部门最高工资,和最低工资的平均工资(字节跳动面试)–窗口函数
- 留存的计算,和累计求和的计算 --窗口函数,自联结(pdd面试)
- AB球队得分流水表,得到连续三次得分的队员名字 和每次赶超对手的球员名字,(pdd面试)
把这几类题型吃透,再也不怕手撕SQL和笔试了,其中最难的是题(5),整个面试的sql基本上都是窗口函数的玩法,搭配case when 也考得比较多。
(1) 找出连续7天登陆,连续30天登陆的用户
1 | select |
(2) 求连续点击三次的用户数,而且中间不能有别人的点击
a表记录了点击的流水信息,包括用户id ,和点击时间
1 | usr_id a a b a a a a |
row_number() over(order by click_time) as rank_1
得到rank_1为 1 2 3 4 5 6 7
row_number() over(partition by usr_id order by click_time)
得到rank_2 为 1 2 1 3 4 5 6
rank_1- rank2
得到diff 为 0 0 2 1 1 1 1
这时我们发现只需要对diff进行分组计数大于3个,就是连续点击大于三且中间没有其他人点击的用户。
1 | select |
(3) 计算除去部门最高工资,和最低工资的平均工资(字节跳动面试)–窗口函数
emp 表
1 | id 员工 id ,deptno 部门编号,salary 工资 |
核心是使用窗口函数降序和升序分别排一遍就取出了最高和最低。
1 | select |
(4) 留存的计算,和累计求和的计算 --窗口函数,自联结(pdd面试)
手机中的相机是深受大家喜爱的应用之一,下图是某手机厂商数据库中的用户行为信息表中部分数据的截图
现在该手机厂商想要分析手机中的**「应用(相机)的活跃情况,」**需统计如下数据:
需要获得的数据的格式如下:
1 | select d.a_t,count(distinct case when d.时间间隔=1 then d.用户id |
(5) AB球队得分流水表,得到连续三次得分的队员名字 和每次赶超对手的球员名字(pdd)
在复盘时发现有类似原题,这是我在面试中遇到的最难的题
问题:两支篮球队进行了激烈的篮球比赛,比分交替上升。比赛结束后,你有一张两队得分分数的明细表,记录了:
- 球队team
- 球员号码number
- 球员姓名name
- 得分分数score
- 得分时间scoretime(datetime)
现在球队要对比赛中表现突出的球员做出嘉奖,所以请你用sql统计出:
- 连续三次(及以上)为球队得分的球员名单
- 比赛中帮助各自球队反超比分的球员姓名以及对应时间。
先建一个类似的表:
1 | CREATE TABLE basketball_game_score_detail( |
这里我使用了lead和lag来取每个组的前几个值,这个和最大联系天数不太一样,但也可以用类似思路去解,但是使用lead和lag做起来更容易理解。
1 | select |
第二小问面试时没完全做出来,说了下思路,现在想了想当时的思路还是有问题,而且这个题也并不难,核心还是记录每个时刻的累计得分表
1 | select |
如下得到每个时刻的累计得分表
1 | select |
计算每个时刻的累计得分差,和上个时间的累计得分差,只要两个的符号相反就是反超时刻。感觉思路还是比较简洁的。
1 | select |
来源:知乎绚丽的小海螺
个人习惯
聊下个人的SQL写作习惯,以上面的最后一个SQL代码为例,在下面的图中我分成了4个部分:
个人的SQL写作几点习惯:
- 关键词小写:标准的写法是关键词比如:
SELECT /ORDER BY/FROM
等都是要大写的;我一般全部都是小写 - 关键词换行:每个关键词单独成行
- select的如果是多个字段,请换行写出每个字段;每个字段的末尾跟上逗号,方便写注释
- 如果是出现了多个子查询,注意换行和嵌套的层级结构