Все же удалось найти способ, уверен кому-то пригодится, в отчетности это один из частых случаев. Я не большой специалист в django, да и по python в целом, поэтому задачку решал в запроснике pma, в mysql есть прекрасный функционал для арифметики дат. В общем это по сути объединение таблиц и фильтрация по двум его полям, чего добиться в django не могу.
SELECT e.id from appname_events as e left join appname_humans as h ON e.human_id=h.id where h.birthdate between DATE_SUB(e.eventDate, interval AGEMAX year) and DATE_SUB(e.eventDate, interval AGEMIN year) ORDER BY e.eventDate DESC
Запрос получился тяжелым, но похоже это меньшее из зол. Выбор только одного столбца дает выиграть время втрое против выборки всех столбцов. Я не уверен как django потом делает свою магию, но в итоге все равно сериализуются "правильные" объекты со всеми полями.
#вьюсет
...
def get_queryset(self):
# получение и валидация ageMin, ageMax из self.request.query_params
...
# выборка и сортировка
query="SELECT e.id from appname_events as e left join appname_humans as h ON e.human_id=h.id where h.birthdate between DATE_SUB(e.eventDate, interval " + ageMax + " year) and DATE_SUB(e.eventDate, interval " + ageMin+ " year) ORDER BY e.eventDate DESC"
queryset=Events.objects.raw(sql)
return queryset
Работает нормально, учитываются високосные года. Из 800 событий и 600 людей на запрос уходит от 0.005 до 0.02 сек, в зависимости от выборки.
Но честно говоря, выглядит костылем, мне все еще кажется, что это как-то средствами django orm можно сделать. Кто знает ответ, обязательно напишите здесь.