Система посещаемости с использованием PHP и MySQL

У меня есть система посещаемости в одном из моих модульных проектов с использованием PHP и MySQL, таблица MySQL выглядит примерно так:

Мои три таблицы MySQL

Теперь расписание используется для хранения таблицы времени для классов за один день для раздела и для которого назначен учитель. Таблица student_info содержит общую информацию о студентах и ​​разделе, к которому они принадлежат. Присутствующий используется для записи тех, кто отсутствует, используя время и идентификатор студента в качестве первичного ключа.

Я мог бы подсчитать, сколько классов было проведено в семестр следующим образом:

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 Inner Join, но не получил того, чего хотел.

Я думал, что первая строка может быть выведена из следующего запроса:

 SELECT timeid FROM timetable WHERE flag > ? AND semester = ? AND section = ? AND timeid BETWEEN ? AND ? 

[UPDATE] Найден способ сделать это, учитывая как ответ, не знаю, правильно ли это.

Заранее благодарю за помощь.

Я, наверное, немного опоздал с моим ответом, но я тоже немного поиграл и придумал решение, которое в основном выполняется в 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; 

Что еще нужно сделать, так это перевод идентификаторов дат в заголовках столбцов на соответствующие даты и, также, перевод идентификаторов студентов в имена или номера univ_roll .

Я также немного поменял макет таблицы: первичный ключ в расписании теперь всего лишь целое число, фактическое время хранится отдельно в другом столбце, обеспечивая гибкость в случае, когда даты или времена могут измениться.

Вот небольшая демонстрация реестров: http://rextester.com/LPFF99061 (таблица посещаемости была заполнена только для первых нескольких дат).

Я не уверен, должен ли я редактировать вопрос с этими обновлениями. Но это частичное решение, с которым я столкнулся. Был бы рад, если бы кто-то мог помочь оптимизировать это больше.

Итак, я начал с этой части кода.

 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 учеников, до примерно 1,6 секунды, когда количество классов составляет всего 39. Я тестирую предыдущие данные и на весь семестр, а код превышает 30 секунд и срабатывает ошибка max_execution_time . На данный момент я установил 25 номеров студентов на каждую страницу.

UPDATE : Ошибка max_execution_time кажется, появляется только в первом запуске, но позже, когда я пытаюсь повторно создать ее, не выдавая больше ошибки, и время, затраченное на выполнение задачи, составляет менее 2 секунд.