分步处理合并找优化
自己蒙头写了大半天,还是要借鉴、学习思想。
6/7级用户
from user_info
where ui.level >5
用户总活跃月份数
里面包含了两个表,所以我们将两表需要的数据取出来并合并,然后进行分组统计个数
select uid, count(distinct s) as act_month_total from (
select uid,DATE_FORMAT(submit_time,'%Y%m') as s from practice_record pr
union all
SELECT uid,DATE_FORMAT(start_time,'%Y%m') as s from exam_record er
)t
group by uid
2021年活跃天数
还是需要将两表合并然后加上2021年的限制
select uid,count(distinct s) as act_days_2021 from (
select uid,DATE_FORMAT(submit_time,'%m%d') as s from practice_record pr
where year(submit_time)=2021
union all
select uid,DATE_FORMAT(start_time,'%m%d') as s from exam_record er
where year(submit_time)=2021
)t1
group by uid
2021年试卷作答活跃天数
需要用到试卷表的按天统计
select uid,count(distinct date_format(start_time,'%m%d')) as act_days_2021_exam
from exam_record
where year(start_time)=2021
group by uid
2021年答题活跃天数
需要用到答题表的按天统计
select uid,count(distinct date_format(submit_time,'%m%d')) as act_days_2021_question
from practice_record
where year(submit_time)=2021
简化
我们可以看到每一步都用到了相同的代码:
- 第一个用到了 年月 进行统计;
- 在后三个都用到的 月日 进行统计
- 有的需要2指定021年
结论
- 所以我们在提取数据的时候将 年月日 一并提取出来;
- 因为后面要区分两个表的数据(答题和试卷)所以添加一个tag标志分别表示两表
- 与用户表右连接以显示所有6、7级的用户,最后分组排序
注意:
- union all 需要两表列数相同,并且两表不需要多余的括号;
- 题目中需要全部展示6、7级的用户,需要用到left join 或right join,连接后相同字段名前指定表名;
- 如使用group by 那么select 后前面的字段必须的聚合函数或者是分组字段
- 年份条件不是每一个字段都需要,所以加到if里面统计
select
ui.uid,
count(distinct left(s,6)) as act_month_total,
count(distinct if(left(s,4)='2021',right(s,4),null)) as act_days_2021,
count(distinct if(left(s,4)='2021' and tag='e',right(s,4),null)) as act_days_2021_exam,
count(distinct if(left(s,4)='2021' and tag='p',right(s,4),null)) as act_days_2021_question
from (
select uid,DATE_FORMAT(submit_time,'%Y%m%d') as s,'p' tag from practice_record pr
union all
SELECT uid,DATE_FORMAT(start_time,'%Y%m%d') as s,'e' as tag from exam_record er
)mon
right join user_info ui
on ui.uid = mon.uid
where ui.level >5
group by uid
order by act_month_total DESC,act_days_2021 desc