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

如何编写SQL查询生成按日期维度统计的学生考勤报表

学生考勤按日期透视SQL实现方案

需求背景

  • 现有学生考勤原始数据
  • 需要输出每名学生对应各日期的考勤情况,最终结果为学生维度行、日期维度列的宽表格式

实现方案

该需求属于典型的SQL行转列(透视)场景,根据使用的数据库类型、日期是否固定,可选择对应写法:

1. 通用静态写法(全数据库兼容,需提前枚举所有统计日期)

如果需要统计的日期范围是固定的,用CASE WHEN+聚合函数的写法可以在所有支持SQL的数据库中运行,无语法兼容问题:

SELECT
  student_id,
  student_name,
  MAX(CASE WHEN attend_date = '2024-01-01' THEN attend_status END) AS `2024-01-01`,
  MAX(CASE WHEN attend_date = '2024-01-02' THEN attend_status END) AS `2024-01-02`,
  MAX(CASE WHEN attend_date = '2024-01-03' THEN attend_status END) AS `2024-01-03`
  -- 按实际需要统计的日期,依次补充对应CASE WHEN语句即可
FROM attendance_raw -- 替换为实际的考勤原始表名
GROUP BY student_id, student_name
ORDER BY student_id;

说明:由于同一个学生同一天只会存在一条考勤记录,用MAX/MIN聚合都可以正常取到唯一的考勤状态,不会出现数据冲突。

2. 动态透视写法(无需手动枚举日期,自动适配日期范围)

如果统计日期不固定,不想每次修改SQL枚举日期,可以用对应数据库的动态语法实现:

MySQL 动态实现

通过拼接动态SQL自动生成所有日期列:

SET @sql = NULL;
-- 自动从源表读取所有不重复的考勤日期,拼接透视逻辑
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN attend_date = ''',
      attend_date,
      ''' THEN attend_status END) AS `',
      attend_date, '`'
    )
  ) INTO @sql
FROM attendance_raw;

-- 拼接完整查询语句并执行
SET @sql = CONCAT('SELECT student_id, student_name, ', @sql, ' 
                  FROM attendance_raw 
                  GROUP BY student_id, student_name
                  ORDER BY student_id');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL Server 实现

用原生PIVOT运算符实现透视,动态场景同样通过拼接SQL实现:

-- 静态PIVOT写法(固定日期)
SELECT student_id, student_name, [2024-01-01], [2024-01-02], [2024-01-03]
FROM attendance_raw
PIVOT(
  MAX(attend_status)
  FOR attend_date IN ([2024-01-01], [2024-01-02], [2024-01-03])
) AS pvt
ORDER BY student_id;

PostgreSQL 实现

用crosstab透视函数实现,首次使用需要先开启扩展:

-- 首次执行需要先创建tablefunc扩展
CREATE EXTENSION IF NOT EXISTS tablefunc;

SELECT *
FROM crosstab(
  'SELECT student_id, student_name, attend_date, attend_status
   FROM attendance_raw
   ORDER BY 1,2,3',
  'SELECT DISTINCT attend_date FROM attendance_raw ORDER BY 1'
) AS final_result(
  student_id INT,
  student_name VARCHAR(50),
  "2024-01-01" VARCHAR(20),
  "2024-01-02" VARCHAR(20),
  "2024-01-03" VARCHAR(20)
  -- 静态场景下补充所有日期字段即可
);

内容的提问来源于stack exchange,提问作者kartik sujith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:48:19