Я застрял с довольно известной проблемой ранжирования учащихся по классам уже пару недель, и хотя я многому научился, я до сих пор не решил свою проблему (ранги сформированы, но процесс слишком медленно):
У меня есть большая таблица (320 000 строк), которая содержит коды учеников (служит вместо идентификаторов их именами), аудиторию учеников, тест, дату экзаменов, предмет, номер вопроса и оценку учеников. по этому вопросу. Эта таблица является основой для всего остального, что вычисляется, и ее размер делает все эти вычисления очень очень медленными, до такой степени, что я нахожу меня почти ломающим все здесь на работе.
Сначала немного информации о школе (очень мало информации, чтобы понять проблему)
Здесь, в школе, мы проводим еженедельные тесты по нескольким предметам. Школа также разделена на классные комнаты с разными целями (одна сфокусирована на математике, физике и химии, другая - биологии, а последняя - истории, португальском и географии). Но все они проводят одни и те же тесты каждую неделю.
То, что мы хотим сделать, - это рассчитать стандартное отклонение для каждого вопроса для всех в школе (не для класса) и средней оценки за вопрос (также для всех в школе), а затем сформировать следующие ранги (все из них на дату):
-Ранк по предмету в классе (с «необработанными» оценками), Ранг по предмету с учетом всей школы (с «необработанными» оценками) и Ранг по предмету с учетом всей школы (с использованием нормированных оценок, со стандартным отклонением на вопрос и средняя оценка за вопрос информации)
Те же ранги, которые были упомянуты выше, но не по предмету, а вместо этого рассматриваются все предметы
Как видите, после расчета средних оценок и стандартных отклонений нам все еще необходимо рассчитать суммы оценок по каждому вопросу и ранжировать в соответствии с этими суммами (фактические оценки по предмету / тесту). Я атаковал эту проблему несколькими способами:
1)
Созданы две таблицы, одна с оценками на каждого учащегося по предмету (поля: код ученика, класс ученика, дата тестирования, предмет, оценка, нормализованная оценка, рейтинг в классе, рейтинг в школе, рейтинг в школе с использованием нормализованных оценок), а другая с оценки на одного учащегося в каждом тесте (все предметы учитываются, поля: код ученика, класс ученика, дата экзамена, оценка, нормализованная оценка, рейтинг в классе, рейтинг в школе, рейтинг в школе с использованием нормализованных оценок).
Вставка данных в эти таблицы занимает около 50 секунд
Затем я попытался использовать SQL для ранжирования, однако столкнулся с некоторыми проблемами:
-Access не имеет функций ROW_NUMBER или RANK, и поэтому я должен использовать запросы с COUNT, например (ниже приведена только упрощенная версия):
SELECT 1+(SELECT Count(*) FROM grades_table_per_subject t2 WHERE
t2.Grade > t1.Grade AND t1.Date=t2.Date AND t1.Subject=t2.Subject) AS [Global Rank],
1+(SELECT Count(*) FROM grades_table_per_subject t3 WHERE t3.Grade > t1.Grade AND
t3.Date=t1.Date AND t3.Subject=t1.Subject AND t3.Classroom=t1.Classroom) AS
[Rank in classroom] FROM grades_table_per_subject;
В запросе все еще есть ранг с нормированными оценками, но я его опустил.
Таблица grades_table_per_subject имеет около 45 000 строк, и этот запрос занимает здесь более 15 минут, даже с индексированием (пробовал много разных комбинаций индексов, даже несколько нечетных, когда я увидел, что те, которые должны работать, не работают).
Я также попытался ORDER BY Count () DESC внутреннее выделение, но я нажал Ctrl + Break через 7 минут и безрезультатно.
2)
В приведенные выше таблицы добавлены следующие поля:
Позиция в классе, Позиция в школе, Позиция в школе с использованием нормированных оценок
Затем я попытался использовать VBA с DAO и вручную обновить поля Rank, запустив следующий код (упрощенная версия):
Set rs = CurrentDb.OpenRecordset("SELECT Classroom, Date, Subject, Grade, [Rank in classroom] FROM
grades_table_per_subject ORDER BY Date, Classroom, Subject, Grade DESC;", dbOpenDynaset)
...
...
rs.movefirst
i=1
While Not rs.eof
'Verifies if there was a change on either one of Subject, Classroom, Date and if so:
...
i = 1
...
rs.Edit
rs![Rank in classroom]=i
rs.Update
i = i + 1
rs.movenext
Wend
rs.close
Это, очевидно, строит только один из рангов (в данном случае на каждого предмета в классе), и это занимает всего 3 минуты 10 секунд.
Я проверил, что это занимает так много времени из-за записей в таблицу (виновниками являются rs.Edit и rs.Update, комментируя их, все запускается всего за 4 секунды), но мне нужны ранги, записанные в таблицу для генерации отчет о доступе позже.
ЗАКЛЮЧИТЕЛЬНО:
Я мог бы сгенерировать все ранги один раз и предоставить пользователям быстрый доступ ко всем данным, но идея в том, что все должно быть рассчитано на лету.Однако достигнутые нами времена делают это невозможным.
В целом, вопрос, который нужно задать, следующий:
-Есть ли способ вычислить показанные выше ранги с помощью запроса на доступ менее чем за 10 секунд или использовать VBA и вычислить-вставить эти рангитаблица в аналогичное время, учитывая размер таблиц, используемых здесь?
Кроме того, я хотел бы увидеть список эффективных алгоритмов ранжирования, так что даже если я не могу все сделать быстро, я могу максимально улучшить его.