You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按年/月统计出勤类型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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:36:52