select uid, COUNT(distinct act_month) AS act_month_total,
COUNT(distinct if(YEAR(act_day) = '2021',act_day, NULL)) AS act_days_2021,
COUNT(distinct if(LEFT(mid,1) = 9 AND YEAR(act_day) = '2021',act_day,NULL)) AS act_days_2021_exam,
COUNT(distinct if(LEFT(mid,1) = 8 AND YEAR(act_day) = '2021',act_day,NULL)) AS act_days_2021_question
FROM (
    select uid, exam_id AS mid,
    date_format(start_time,'%Y%m') AS act_month, 
    date_format(start_time,'%Y%m%d') AS act_day
    FROM user_info 
    LEFT JOIN exam_record using(uid)
    WHERE level = 6 OR level = 7
    union all
    select uid, question_id AS mid,
    date_format(submit_time,'%Y%m') AS act_month, 
    date_format(submit_time,'%Y%m%d') AS act_day
    FROM  user_info           
    LEFT JOIN  practice_record using(uid)
    WHERE level = 6 OR level = 7
) AS t
GROUP BY uid
ORDER BY act_month_total DESC,act_days_2021 DESC

思路:请统计每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、2021年答题活跃天数

要将试卷表和题目表合并统计,所以用union all合并两个查询,

试卷id和题目id分别是9和8开头,在统计他们分别的数量时可以用LEFT(mid,1) = 9 or 8 区分

需要注意的是有些用户没有作答记录,他们的数都为0 在合并用户信息表和作答表时,应该要返回用户信息表的所有行,即使没有作答记录

在 SQL 的 LEFT JOIN 中,左表是位于 LEFT JOIN 关键字之前的表,而右表是位于 LEFT JOIN 关键字之后的表。

例如,在以下查询中:

SELECT *
FROM table1
LEFT JOIN table2 ON table1.column = table2.column;

在这个查询中,table1 是左表,而 table2 是右表。LEFT JOIN 保证了左表中的所有行都会出现在结果中,即使右表中没有与之匹配的行,右表中的列也会显示为 NULL。right join 与之相反