我的一个模块项目中有一个使用PHP和MySQL的考勤系统,MySQL表看起来像这样:
现在,时间表用于存储一天中课程的时间表以及分配给哪位教师。 student_info 表包含有关学生及其所属部分的一般信息。 考勤用于记录使用时间和学生ID作为主键缺席的人。
我可以计算一个学期的课程数量如下:
SELECT count(*) as total FROM timetable WHERE flag > ? AND semester = ? AND section = ? AND timeid BETWEEN ? AND ?
然后计算学生参加的次数,并计算出勤率。
SELECT stu.* ,
(SELECT COUNT(*)
FROM attendancetable att
WHERE att.s_id = stu.class_roll
AND att.semester = ?
AND att.timeid BETWEEN ? AND ? ) AS absent
FROM student_info stu
WHERE stu.section = ?
AND stu.logYear = ?
AND stu.deleted = ?
ORDER BY stu.class_roll
现在,我还要显示一种考勤表如下:
我尝试了SQL内部加入,但没有得到我想要的方式。
我在想第一行可以从以下查询中输出:
SELECT timeid
FROM timetable
WHERE flag > ?
AND semester = ?
AND section = ?
AND timeid BETWEEN ? AND ?
[更新]找到一种方法来做到这一点,作为答案,不知道这是否正确。
提前感谢您的帮助。
答案 0 :(得分:1)
我的答案可能有点迟了,但我也玩过一段时间并提出了一个主要在MySql中完成的解决方案:我的解决方案构建了一个动态SELECT
语句,该语句在最后给我提供表格,列有预定时代的列:
SET @str='SELECT sid';
SELECT @str:=concat(@str,', MAX(CASE tid WHEN ',t_id,
' THEN \'OK\' ELSE \'\' END) d',t_id)
-- start date end date
FROM times WHERE dati BETWEEN '20170810.0000' and '20171022.2359';
SET @str=concat(@str,' FROM att GROUP BY sid');
PREPARE qu FROM @str;
EXECUTE qu;
还需要做的是将列标题中的日期ID转换为正确的日期,同样地,将学生ID转换为名称或univ_roll
数字。
我也可以自由地改变表格布局:时间表中的主键现在只是一个整数,实际时间分别存储在另一列中,在日期或时间可能发生变化的情况下提供灵活性。
这是一个小的rextester演示:http://rextester.com/LPFF99061(出勤表仅在前几个日期填写)。
答案 1 :(得分:0)
我不确定是否应该使用这些更新编辑问题。但这是我做出的部分解决方案。如果有人可以帮助进一步优化这一点,那将会很高兴。
所以,我从这段代码开始。
SELECT timeid
FROM timetable
WHERE flag > ?
AND semester = ?
AND section = ?
AND timeid BETWEEN ? AND ?
从上面的代码我可以得到上课的日期。接下来,我会检查学生是否在所提及的日期出现或缺席如下:
SELECT attended FROM attendancetable
WHERE s_id = ?
AND semester = ?
AND timeid = ?
有了这个,我就能看出学生是否缺席。在php中它看起来像这样:
//Getting the dates
$query = "SELECT timeid FROM timetable
WHERE flag > ?
AND semester = ?
AND section = ?
AND timeid BETWEEN ? AND ?";
$params = array(0, 1, 'A', '2017-01-01', '2017-06-30' );
$stmt = $db->prepare($query);
$stmt->execute($params);
$dates = $stmt->fetchall();
//checking if students is present or absent
$query = "SELECT attended FROM attendancetable
WHERE s_id = ?
AND semester = ?
AND timeid = ?";
//Now I'm going to loop through the $dates
foreach($dates as $date){
$params = array(1, 'A', $date['timeid']);
$stmt = $db->prepare($query);
$stmt->execute($params);
$result = $stmt->fetchall();
($result) ? $present = 1 : $present = 0;
}
通过上述方式,我能够根据时间表计算某个特定部分的学生是否出现在某一特定班级。现在,如果我想要一个部分中的所有学生,我可以先查询student_info
表,然后计算每个学生的foreach
循环
SELECT class_roll FROM student_info
WHERE logYear = ?
AND section = ?
AND deleted = ?
ORDER BY class_roll LIMIT ?, ?
然后每个学生都要经过foreach循环来检查他们是否缺席或在场。最后,我可以得到这个:
我在本地测试了大约200名学生的执行时间,当课程数量只有39时,大约需要1.6秒。我还测试了以前的数据整整一个学期,代码超过30秒{{1}错误触发。截至目前,我每页设置了25个学生限制。
更新 :max_execution_time
错误似乎只出现在第一次运行时,但稍后当我尝试重新生成它不再给出错误时完成任务所需的时间不到2秒。