明确题意:
请统计每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、2021年答题活跃天数,按照总活跃月份数、2021年活跃天数降序排序。
问题分解:
- 统计每个用户的总活跃月份数、2021年活跃天数,生成子表 t_2021_total_act:
- 统计每个用户的每天活跃情况,生成子表 t_merge_record :
- 统计试卷区用户活跃情况:distinct uid, DATE(start_time) as active_date
- 统计试题区用户活跃情况:distinct uid, DATE(submit_time) as active_date
- 合并上述活跃情况:UNION ALL
- 按用户分组:GROUP BY uid
- 统计总活跃月份数:COUNT(distinct DATE_FORMAT(active_date, "%Y%m")) as act_month_total
- 统计2021年活跃天数:COUNT(distinct if(YEAR(active_date)=2021, active_date, null)) as act_days_2021
- 统计每个用户的每天活跃情况,生成子表 t_merge_record :
- 统计2021年题目练习活跃天数,生成子表 t_2021_act_days_question:
- 筛选2021年的记录:WHERE YEAR(submit_time)=2021
- 按用户分组:GROUP BY uid
- 统计活跃天数:COUNT(distinct DATE(submit_time)) as act_days_2021_question
- 统计2021年试卷作答活跃天数,生成子表 t_2021_act_days_exam:
- 筛选2021年的记录:WHERE YEAR(start_time)=2021
- 按用户分组:GROUP BY uid
- 统计活跃天数:COUNT(distinct DATE(start_time)) as act_days_2021_exam
- 左连接user_info和上述3个子表(左连接是因为题目要求输出每个满足属性条件的用户的各类指标,即使都为0):
- 筛选用户级别:WHERE user_info.level > 5
- 特殊处理指标为0的情况,为0时左连接结果会是NULL:ifnull(act_month_total, 0) as act_month_total (其他指标写法一样)
细节问题:
- 表头重命名:as
- 按总活跃月份数、2021年活跃天数降序排序:ORDER BY act_month_total DESC, act_days_2021 DESC
完整代码:
SELECT user_info.uid as uid,
ifnull(act_month_total, 0) as act_month_total,
ifnull(act_days_2021, 0) as act_days_2021,
ifnull(act_days_2021_exam, 0) as act_days_2021_exam,
ifnull(act_days_2021_question, 0) as act_days_2021_question
FROM user_info
LEFT JOIN (
SELECT uid,
COUNT(distinct DATE_FORMAT(active_date, "%Y%m")) as act_month_total,
COUNT(distinct if(YEAR(active_date)=2021, active_date, null)) as act_days_2021
FROM (
SELECT distinct uid, DATE(start_time) as active_date FROM exam_record
UNION ALL
SELECT distinct uid, DATE(submit_time) as active_date FROM practice_record
) as t_merge_record
GROUP BY uid
) AS t_2021_total_act USING(uid) -- 总活跃月份数、2021年活跃天数
LEFT JOIN (
SELECT uid, COUNT(distinct DATE(submit_time)) as act_days_2021_question
FROM practice_record
WHERE YEAR(submit_time)=2021
GROUP BY uid
) as t_2021_act_days_question USING(uid) -- 2021年题目练习活跃天数
LEFT JOIN (
SELECT uid, COUNT(distinct DATE(start_time)) as act_days_2021_exam
FROM exam_record
WHERE YEAR(start_time)=2021
GROUP BY uid
) as t_2021_act_days_exam USING(uid) -- 2021试卷作答活跃天数
WHERE user_info.level > 5
ORDER BY act_month_total DESC, act_days_2021 DESC;