一、考总结拓展&完整代码
题设的考点通篇围绕这几个聚合窗口函数以及结合GROUP BY函数的使用。
1) 聚合窗口函数
- MIN()OVER() :不改变表结构的前提下,计算出最小值
- MAX()OVER():不改变表结构的前提下,计算出最大值
- COUNT()OVER():不改变表结构的前提下,计数
- SUM()OVER():不改变表结构的前提下,求和
- AVG()OVER():不改变表结构的前提下,求平均值
- percent_rank() over() 按照数字所在的位置进行百分位分段
- ntile(n)over() 将数字按照大小平均分成n段
- lead(字段名,n)over()把字段数据向前移n个单元格
- lag(字段名,n)over()把字段数据向后移n个单元格
3)完整代码
SELECT start_month ,#每个月 COUNT(DISTINCT uid) mau, #月活用户数 SUM(new_day) month_add_uv, #新增用户 MAX(SUM(new_day))OVER(ORDER BY start_month) max_month_add_uv, #截止当月的单月最大新增用户数 SUM(SUM(new_day))OVER(ORDER BY start_month) cum_sum_uv FROM ( SELECT *,DATE_FORMAT(start_time,'%Y%m') start_month, IF(start_time=MIN(start_time)OVER(PARTITION BY uid),1,0) new_day FROM exam_record)t1 GROUP BY start_month;
二、题目解读与解题步骤拆分
1、题目解读
求:请输出自从有用户作答记录以来,每月的试卷作答记录中月活用户数、新增用户数、截止当月的单月最大新增用户数、截止当月的累积用户数。结果按月份升序输出
题目中隐藏的坑&难点
- 坑1:新增用户的定义——首次登录的用户,也就是把用户最早登录的那天定义为首次登录日期。
- 坑2:截止当月的单月最大新增用户数:按照月份依次对比每个月的新增用户数的大小取大值用MAX()OVER(order by start_month)
- 坑3:截止当月的累积用户数:按照月份依次累加新增用户数用SUM()OVER(ORDER BY start_month)
需求字段:
- start_month :月份
- mau :月活用户数
- month_add_uv :新增用户数
- max_month_add_uv:截止当月的单月最大新增用户数
- cum_sum_uv:截止当月的累积用户数
2、步骤拆分
思路比较简单,就是先处理新用户数据,再用窗口函数进行各种查询。
先基于原表,新增一列对新用户的定义列:定义新增用户“首次登录日取1,其他日期取0”,建立子表t1。再基于t1的基础上查询月活用户数,新增用户数,截止当月的单月最大新增用户数,截止当月的累积用户数。
三、步骤代码
1)定义新用户
- 先查每一个用户的首次登录日期
MIN(start_time)OVER(PARTITION BY uid) AS new_user_day #第一天登录
- 定义新用户
IF(start_time = new_user_day,1,0) AS new_day # 若用户的登录时间等于首次登录时间则定义为新用户,新用户被标记为1,其他标记为0。 IF(start_time=MIN(start_time)OVER(PARTITION BY uid),1,0) AS new_day #完整的表达
- 新用户被定义出来后运行该代码可得下表
SELECT *,DATE_FORMAT(start_time,'%Y%m') start_month, IF(start_time=MIN(start_time)OVER(PARTITION BY uid),1,0) new_day FROM exam_record #子表命名为t1
2)统计月活用户
- 月活用户需要去重COUNT(DISTICT uid) mau
3)统计月新增用户
- 对每天的新增用户进行求和SUM(new_day) month_add_uv
SELECT start_month ,#每个月 COUNT(DISTINCT uid) mau, #月活用户数 SUM(new_day) month_add_uv #新增用户 FROM ( SELECT *,DATE_FORMAT(start_time,'%Y%m') start_month, IF(start_time=MIN(start_time)OVER(PARTITION BY uid),1,0) new_day FROM exam_record)t1 GROUP BY start_month ;
4)查找截止当月的单月最大新增用户数
- 使用窗口函数按月依次查找最大每个月最大的新增用户数MAX(month_add_uv)OVER(order by start_month)
5)统计截止当月的累积用户数
- 使用窗口函数按月累加新增用户数SUM(month_add_uv)OVER(order by start_month)
6)按月份升序输出&完整代码

SELECT start_month ,#每个月 COUNT(DISTINCT uid) mau, #月活用户数 SUM(new_day) month_add_uv, #新增用户 MAX(SUM(new_day))OVER(ORDER BY start_month) max_month_add_uv, #截止当月的单月最大新增用户数 SUM(SUM(new_day))OVER(ORDER BY start_month) cum_sum_uv FROM ( SELECT *,DATE_FORMAT(start_time,'%Y%m') start_month, IF(start_time=MIN(start_time)OVER(PARTITION BY uid),1,0) new_day FROM exam_record)t1 GROUP BY start_month;