分步处理合并找优化

自己蒙头写了大半天,还是要借鉴、学习思想。

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

简化

我们可以看到每一步都用到了相同的代码:

  1. 第一个用到了 年月 进行统计;
  2. 在后三个都用到的 月日 进行统计
  3. 有的需要2指定021年

结论

  • 所以我们在提取数据的时候将 年月日 一并提取出来;
  • 因为后面要区分两个表的数据(答题和试卷)所以添加一个tag标志分别表示两表
  • 与用户表右连接以显示所有6、7级的用户,最后分组排序

注意:

  1. union all 需要两表列数相同,并且两表不需要多余的括号;
  2. 题目中需要全部展示6、7级的用户,需要用到left join 或right join,连接后相同字段名前指定表名;
  3. 如使用group by 那么select 后前面的字段必须的聚合函数或者是分组字段
  4. 年份条件不是每一个字段都需要,所以加到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