需求:
场景:老师布置了一个任务,分为n天训练。任务会分配给m个学生。使用一张表来记录学生和训练的关系。即task_plan_info_stu表。
表结构:
CREATE TABLE `task_plan_info_stu` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`plan_info_id` bigint(20) DEFAULT NULL COMMENT '每日练习id',
`task_id` bigint(20) DEFAULT NULL COMMENT '任务id',
`school_id` int(11) DEFAULT NULL COMMENT '学校',
`stu_num` varchar(255) DEFAULT NULL COMMENT '学号',
`create_time` datetime DEFAULT NULL,
`update_time` timestamp NULL DEFAULT NULL,
`creator_id` varchar(255) DEFAULT NULL,
`correct_status` int(11) DEFAULT NULL COMMENT '提交状态 0:未提交1:已提交',
PRIMARY KEY (`id`),
KEY `idx_plan_info_id` (`plan_info_id`) USING BTREE,
KEY `idx_task_id` (`task_id`),
KEY `idx_student` (`stu_num`,`school_id`) USING BTREE
) ENGINE=InnoDB CHARSET=utf8;
需求:给定多个taskId,来确定各个任务已完成的人数。
因为是获取每个任务未完成的学生信息,所以需要以任务和学生进行分组。
ps:任务已完成,代表一个学生将n天的练习均提交!
分析
若存在x个任务,来统计各个任务的完成人数。我们可以从未完成学生进行考虑。
(1)筛选
筛选未提交的记录。
(2)分组
这张表的数据:x*n*m个。(x表示任务数,m表示学生数,n表示每个任务的练习天数(n不固定))
以任务分组:即存在x条记录,一个任务下有m个学生,一个学生又有n天练习。
我们想得到每个任务下,未完成的人数,那么先以任务分组,在以学生分组。此时最多得到x*m条记录。
因为经过筛选,当前均是未提交的数据,只要该学生有一天没有提交,那么便可以筛选出该学生信息,筛选出的记录x*y【y是未全部提交的学生数量】。
然后在以得到的记录作为数据源,对任务再次分组,得到未提交学生的数量。
select x.task_id,count(*)
from(
select i.task_id task_id from task_plan_info_stu i
where i.task_id in (12121,21212) and i.correct_status=0
group by i.task_id,i.school_id,i.stu_num) x
GROUP BY x.task_id
扩展
GROUP_CONCAT(expr)
函数:在select上使用,作用是返回某个非分组字段的值,获取的值默认使用,
进行分割。
举个例子,在学生表中,使用学校进行分组,但是想返回每个学校的学生编号,就可以使用GROUP_CONCAT(expr)
函数:
select school_id,GROUP_CONCAT(id)
from t_stu
group by school_id;