У меня есть сложная модель базы данных, настроенная в Django, и мне нужно сделать ряд вычислений на основе данных фильтра. У меня есть объект Test
, объект TestAttempt
и объект UserProfile
(с внешним ключом к test и внешним ключом к userprofile). Есть метод, который я запускаю на TestAttempt
, который вычисляет оценку теста (основанную на количестве вариантов, предложенных пользователем, по сравнению с правильными ответами, связанными с каждым тестом). И еще один метод, который я запускаю на Test
и который вычисляет средний балл теста на основе каждого из связанных с ним TestAttempt
Но иногда мне нужно среднее значение на основе только заданного подмножества связанных TestAttempt
, которые связаны с определенным набором UserProfiles
. Поэтому вместо того, чтобы вычислять средний тестовый балл для конкретного теста таким образом:
[x.score() for x in self.test_attempts.all()]
и затем усреднять эти значения. Я делаю такой запрос:
[x.score() for x in self.test_attempts.filter(profile__id__in=user_id_list).all()]
где user_id_list
- это определенное подмножество идентификаторов UserProfile, для которых я хочу найти средний тестовый балл в виде списка. Мой вопрос заключается в следующем: если user_id_list
- это действительно весь набор UserProfile
(поэтому фильтр вернет то же самое, что и self.test_attempts. all()
) и в большинстве случаев так и будет, стоит ли проверять этот случай, и если да, то не выполнять фильтр вообще? Или __in поиск достаточно эффективен, что даже если user_id_list
содержит всех пользователей, эффективнее будет запустить фильтр. Также, нужно ли мне беспокоиться о том, чтобы результирующие test_attempts были distinct()? Или они не могут оказаться дубликатами с учетом структуры моего набора запросов?
EDIT: Для тех, кому интересно посмотреть на необработанный SQL-запрос, он выглядит вот так без фильтра:
SELECT "mc_grades_testattempt"."id", "mc_grades_testattempt"."date",
"mc_grades_testattempt"."test_id", "mc_grades_testattempt"."student_id" FROM
"mc_grades_testattempt" WHERE "mc_grades_testattempt"."test_id" = 1
и вот так с фильтром:
SELECT "mc_grades_testattempt"."id", "mc_grades_testattempt"."date",
"mc_grades_testattempt"."test_id", "mc_grades_testattempt"."student_id" FROM
"mc_grades_testattempt" INNER JOIN "mc_grades_userprofile" ON
("mc_grades_testattempt"."student_id" = "mc_grades_userprofile"."id") WHERE
("mc_grades_testattempt"."test_id" = 1 AND "mc_grades_userprofile"."user_id" IN (1, 2, 3))
обратите внимание, что массив (1,2,3) - это просто пример