select distinct uid,count(if(submit_time is null,1,null)) incomplete_cnt,count(if(submit_time is null,null,1)) complete_cnt,group_concat(distinct date_format(start_time,'%Y-%m-%d'),':',tag order by start_time separator ';')
from exam_record r
join examination_info i
on r.exam_id = i.exam_id
where year(start_time)='2021'
group by uid
having complete_cnt >= 1 and incomplete_cnt > 1 and incomplete_cnt < 5
order by incomplete_cnt desc

主要还是group_concat的用法

group_concat:将分组中括号里对应的字符串进行拼接。如果分组中括号里的参数有多行,那么肯定会将这多行的字符串连接,每个字符串之间有特定的符号进行分隔。

group_concat( [distinct] 列名1 [order by 列名2 asc/desc] [separator ,])

将分组中的列名1这一列对应的多行的值按照列名2 升序或者降序进行连接,其中分隔符为 ,

然后就是注意对数据进行去重,因为一个人可能对一张数据进行多次作答,但是多次作答结果都是未完成或者完成

最后就是在有效用户的基础上再进行筛选