当前位置: 首页 > news >正文

SQL188 每月及截止当月的答题情况

 一、题目描述

现有试卷作答记录表 exam_record,字段如下:

现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分):

iduidexam_idstart_timesubmit_timescore
1100190012020-01-01 09:01:012020-01-01 09:21:5990
2100290012020-01-20 10:01:012020-01-20 10:10:0189
3100290012020-02-01 12:11:012020-02-01 12:31:0183
4100390012020-03-01 19:01:012020-03-01 19:30:0175
5100490012020-03-01 12:01:012020-03-01 12:11:0160
6100390012020-03-01 12:01:012020-03-01 12:41:0190
7100290012020-05-02 19:01:012020-05-02 19:32:0090
8100190022020-01-02 19:01:012020-01-02 19:59:0169
9100490022020-02-02 12:01:012020-02-02 12:20:0199
10100390022020-02-02 12:01:012020-02-02 12:31:0168
11100190022020-01-02 19:01:012020-02-02 12:43:0181
12100190022020-03-02 12:11:01(NULL)(NULL)

请输出自从有用户作答记录以来,每月的试卷作答记录中月活用户数、新增用户数、截止当月的单月最大新增用户数、截止当月的累积用户数。结果按月份升序输出。

  • 新增用户:首次登录的用户,也就是把用户最早登录的那天定义为首次登录日期。
  • 截止当月的单月最大新增用户数:按照月份依次对比每个月的新增用户数的大小取大值
  • 截止当月的累积用户数:按照月份依次累加新增用户数

需求字段:

  • start_month :月份
  • mau :月活用户数
  • month_add_uv :新增用户数
  • max_month_add_uv:截止当月的单月最大新增用户数
  • cum_sum_uv:截止当月的累积用户数


由示例数据结果输出如下:

start_monthmaumonth_add_uvmax_month_add_uvcum_sum_uv
2020012222
2020024224
2020033024
2020051024

month1001100210031004
20200111
2020021111
202003111
2020051

由上述矩阵可以看出,2020年1月有2个用户活跃(mau=2),当月新增用户数为2;

2020年2月有4个用户活跃,当月新增用户数为2,最大单月新增用户数为2,当前累积用户数为4。

 


 二、核心难点解析

难点1:什么是“新增用户”?

新增 ≠ 当月活跃
新增 = 该用户的第一次作答记录所在的月份

必须先识别每个用户的“首次行为”,不能直接对当月数据去重。


难点2:如何标记“首次行为”?

正确方法:使用窗口函数 ROW_NUMBER()

ROW_NUMBER() OVER (PARTITION BY uid ORDER BY start_time) AS rn
  • PARTITION BY uid:按用户分组
  • ORDER BY start_time:按时间排序
  • rn = 1:表示这是该用户的第一次作答
  • rn > 1:老用户回访

关键洞察: rn = 1 的记录,就是“新增用户”的发生时刻!


 三、最终简洁版 SQL(推荐写法)

-- 第一步:给每条记录标记是否是用户首次作答
WITH user_behavior AS (SELECTuid,start_time,ROW_NUMBER() OVER (PARTITION BY uid ORDER BY start_time) AS rnFROM exam_record
)-- 第二步:按月份统计所有指标
SELECTDATE_FORMAT(start_time, '%Y%m') AS start_month,           -- 月份COUNT(DISTINCT uid) AS mau,                              -- 月活用户数SUM(CASE WHEN rn = 1 THEN 1 ELSE 0 END) AS month_add_uv, -- 当月新增用户数MAX(SUM(CASE WHEN rn = 1 THEN 1 ELSE 0 END)) OVER (ORDER BY DATE_FORMAT(start_time, '%Y%m')) AS max_month_add_uv, -- 截止当月最大新增SUM(SUM(CASE WHEN rn = 1 THEN 1 ELSE 0 END)) OVER (ORDER BY DATE_FORMAT(start_time, '%Y%m')) AS cum_sum_uv        -- 截止当月累积用户数
FROM user_behavior
GROUP BY DATE_FORMAT(start_time, '%Y%m')  -- 按月分组
ORDER BY start_month;

🔍 四、代码逐行解析

代码作用为什么这样写?
WITH user_behavior AS (...)创建临时表,提前计算 rn让主查询更清晰,逻辑分层
ROW_NUMBER() ... AS rn标记用户首次行为rn=1 就是“新增”
COUNT(DISTINCT uid)统计当月活跃的去重用户数标准 mau 计算
SUM(CASE WHEN rn=1 THEN 1 ELSE 0 END)统计当月有多少用户的“第一次”发生这就是“当月新增用户数”
MAX(SUM(...)) OVER(...)对“每月新增数”取历史最大值MAX() OVER(ORDER BY 月)
SUM(SUM(...)) OVER(...)对“每月新增数”做累加SUM() OVER(ORDER BY 月)

 五、核心思想总结

1. “新增用户”问题的通用解法

“先标记,再统计”

-- 万能模板
ROW_NUMBER() OVER (PARTITION BY uid ORDER BY 时间) AS rn

然后用 CASE WHEN rn = 1 THEN 1 ELSE 0 END 打标。


2. 窗口函数嵌套聚合函数

MAX(SUM(...)) OVER (ORDER BY ...)
  • 外层 SUM(...):先算出每月的值
  • 内层 MAX/OVER:再对这些值做累积或取最大
  • 适用场景: 累积、历史最大、移动平均等

3. 为什么不能用“总用户 - 上月”?

  • 因为用户可能流失、回流,逻辑不严谨
  • “新增”是基于用户生命周期的,必须从源头识别
http://www.dtcms.com/a/532559.html

相关文章:

  • 珠海网站专业制作网站开发和运维区别
  • 数据格式 、序列化和反序列化
  • 【Rust编程:从新手到大师】第一个项目Hello,World
  • 【代码随想录算法训练营——Day48】单调栈——42.接雨水、84.柱状图中最大的矩形
  • 架构设计:银行核心系统
  • 手机网站建设推广网站策划书格式
  • Week 22: 深度学习补遗:Transformer+Encoder构建
  • Nacos,什么是Nacos,一文详解
  • 7. Qt 容器迭代器
  • 详解MySQL两种存储引擎MyISAM和InnoDB的优缺点
  • Python + uiautomator2 手机自动化控制教程
  • 黑龙江省城乡建设厅网站注册广告公司名字
  • 杨校老师课堂之C++备赛信奥中STL常用库函数梳理汇总(含样例代码)
  • UU远程深度测评:聚焦游戏与Windows多屏场景,免费实用的远程控制选择
  • week7
  • 【Python刷力扣hot100】15. 3Sum
  • MacOS平台Keil代替方案
  • 建设项目技术服务网站笋岗网站建设
  • 【AI原生架构:数据架构】10、从主数据治理到价值落地
  • jQuery JSONP详解
  • GitHub等平台形成的开源文化正在重塑和解
  • 网站首页包含的内容wordpress扩展class名称
  • MCoT在医疗AI工程化编程的实践手册(上)
  • 济南网站建设淄博外贸网站哪家好
  • 阮一峰《TypeScript 教程》学习笔记——类型工具
  • 怎样做钓鱼网站网站建设电话营销话术
  • 51c大模型~合集32
  • 生物化学Learning Track(14)酶催化机制
  • 力扣2:两数相加
  • 构建通用并发下载工具:用Golang重构wget脚本的实践分享