思路
老办法啊,遇到这种套娃题目我们就拆:
**每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、2021年答题活跃天数,**按照总活跃月份数、2021年活跃天数降序排序
一眼看去,最简单的是什么?
2021年试卷作答活跃天数、2021年答题活跃天数
注意这里有一个坑:2021年活跃天数 != 2021年试卷作答活跃天数+2021年答题活跃天数,如果同一天完成试卷跟答题依然是一天
2021年试卷作答活跃天数
select
uid,
count(distinct date(submit_time))
FROM
practice_record
WHERE
year(submit_time) = 2021
group by
uid
如法炮制
2021年答题活跃天数
select
uid,
count(distinct date(start_time))
FROM
exam_record
WHERE
year(start_time) = 2021
GROUP BY
uid;
但是uid有问题,这俩uid不一定一样的,也就是说这俩表连的话不能确定谁是主表谁是从表
那咋办呢?这俩的uid一定在user_info里面于是就三表连接
用这个来进行筛选和数人。
count(distinct if(YEAR(e_r.start_time)=2021,date(e_r.start_time),null))
count(distinct if(YEAR(p_r.submit_time)=2021,date(p_r.submit_time),null))
综合
select
u_i.uid,
count(distinct if(YEAR(e_r.start_time)=2021,date(e_r.start_time),null)) act_days_2021_exam,
count(distinct if(YEAR(p_r.submit_time)=2021,date(p_r.submit_time),null)) act_days_2021_queston
from
exam_record e_r
right JOIN
user_info u_i
ON
e_r.uid = u_i.uid
LEFT JOIN
practice_record p_r
ON
u_i.uid = p_r.uid
WHERE
level > 5
GROUP BY
u_i.uid
order by
act_month_total desc ,act_days_2021 desc;
顺带把level解决,那前面的俩难搞的怎么办呢?
总活跃月份数、2021年活跃天数
select
uid,
count(distinct date_format(start_time, '%Y%m')) act_month_total,
count(distinct if(YEAR(start_time)=2021,date_format(start_time, '%Y%m%d'),null)) act_days_2021
from (select
uid,
submit_time start_time
from practice_record
union
select
uid,
start_time
from exam_record) mon
group by
uid
又是两层查询,一层链接表,一层筛选
所以将结果再连起来就成了
通过代码1
select
u_i.uid,
ifnull(act_month_total,0) act_month_total,
ifnull(act_days_2021,0)act_days_2021,
count(distinct if(YEAR(e_r.start_time)=2021,date(e_r.start_time),null)) act_days_2021_exam,
count(distinct if(YEAR(p_r.submit_time)=2021,date(p_r.submit_time),null)) act_days_2021_queston
from
exam_record e_r
right JOIN
user_info u_i
ON
e_r.uid = u_i.uid
LEFT JOIN
practice_record p_r
ON
u_i.uid = p_r.uid
left join (
select
uid,
count(distinct date_format(start_time, '%Y%m')) act_month_total,
count(distinct if(YEAR(start_time)=2021,date_format(start_time, '%Y%m%d'),null)) act_days_2021
from (select
uid,
submit_time start_time
from practice_record
union
select
uid,
start_time
from exam_record) mon
group by
uid
) mon
on mon.uid = u_i.uid
WHERE
level > 5
GROUP BY
u_i.uid
order by
act_month_total desc ,act_days_2021 desc
代码又臭又长,表的利用率贼低,基本就是连接了6个表嵌套查询
问题出在哪?
select
uid,
submit_time start_time
from practice_record
union
select
uid,
start_time
from exam_record
这个表,理论上来说可以完成后两个要求,也就是我们的第一第二的需求,但是我们需要一个标记将上下块标记开,也就是标记出来做卷子跟做题
所以:
select
uid,
submit_time start_time,
'1' tag
from practice_record
union
select
uid,
start_time,
'2' tag
from exam_record
然后
count(distinct if(YEAR(start_time)=2021 and tag = '1',date(start_time),null)) act_days_2021_exam,
count(distinct if(YEAR(start_time)=2021 and tag = '2',date(start_time),null)) act_days_2021_queston
通过代码2
select
u_i.uid,
count(distinct date_format(start_time, '%Y%m')) act_month_total,
count(distinct if(YEAR(start_time)=2021,date_format(start_time, '%Y%m%d'),null)) act_days_2021,
count(distinct if(YEAR(start_time)=2021 and tag = '2',date(start_time),null)) act_days_2021_exam,
count(distinct if(YEAR(start_time)=2021 and tag = '1',date(start_time),null)) act_days_2021_queston
from (select
uid,
submit_time start_time,
'1' tag
from practice_record
union
select
uid,
start_time,
'2' tag
from exam_record) mon
right join user_info u_i
on u_i.uid = mon.uid
where u_i.level >5
group by
uid
order by
act_month_total desc ,act_days_2021 desc;
看起来顺眼多了