按年/月统计出勤类型SQL查询异常:返回非当年数据求助
排查你的SQL出勤统计问题
我一眼就看出问题出在你那些独立的子查询上——它们完全没和外层的class表日期条件关联!
问题根源分析
你外层的WHERE YEAR(Date_class) = YEAR(CURDATE())确实过滤了class表的当年数据,但你写的每个统计子查询(比如(SELECT COUNT(distinct ID) FROM presences WHERE Presence = 0))都是全局全量统计,完全忽略了外层的年份限制,也没绑定当前分组的月份。不管外层取的是哪年哪月的班级记录,这些子查询都会返回所有时间里符合条件的出勤记录数,这就是结果混入往年数据的原因。
另外,你用的隐式内连接写法,虽然加了presences.Id_class = class.ID,但这个关联只作用于外层表的连接,对子查询没有任何约束,等于子查询是独立运行的。
修正后的SQL方案
我们可以用LEFT JOIN关联两张表,结合CASE WHEN在分组中直接统计当月的出勤类型数量,这样能确保统计范围严格限定在当年当月:
SELECT DATE_FORMAT(c.Date_class, '%Y') AS `year`, DATE_FORMAT(c.Date_class, '%M') AS `month`, COUNT(DISTINCT CASE WHEN p.Presence = 0 THEN p.ID END) AS Faltas, COUNT(DISTINCT CASE WHEN p.Presence = 1 THEN p.ID END) AS Pre, COUNT(DISTINCT CASE WHEN p.Presence = 2 THEN p.ID END) AS Temp, COUNT(DISTINCT CASE WHEN p.Presence = 3 THEN p.ID END) AS Canc, COUNT(DISTINCT CASE WHEN p.Presence = 4 THEN p.ID END) AS FaltasTemp FROM class c LEFT JOIN presences p ON p.Id_class = c.ID WHERE YEAR(c.Date_class) = YEAR(CURDATE()) GROUP BY DATE_FORMAT(c.Date_class, '%Y%m') ORDER BY YEAR(c.Date_class), MONTH(c.Date_class);
额外优化提示
- 我注意到你用
COUNT(distinct ID)统计的是出勤记录的ID,如果你的需求是统计不同学生的出勤类型,应该把p.ID换成p.Id_student,这样才是按学生维度去重统计,而非按单条出勤记录。 - 加上
ORDER BY可以让结果按年月顺序排列,更适配柱状图的展示逻辑。
内容的提问来源于stack exchange,提问作者Cracktastic
相关产品推荐
相关产品推荐

