python - Django - Time aggregates of DatetimeField across queryset -
(using django 1.11.2, python 2.7.10, mysql 5.7.18)
if imagine simple model:
class event(models.model): happened_datetime = datetimefield() value = integerfield()
what elegant (and quickest) way run similar to:
res = event.objects.all().aggregate( avg('happened_datetime') )
but able extract average time of day members of queryset. like:
res = event.objects.all().aggregate( avgtimeofday('happened_datetime') )
would possible on db directly?, i.e., without running long loop client-side each queryset member?
edit:
there may solution, along lines, using raw sql:
select sec_to_time(avg(time_to_sec(extract(hour_second happened_datetime)))) event_event;
performance-wise, runs in 0.015 second ~23k rows on laptop, not optimised, etc. assuming could yield accurate/correct results , since time secondary factor, using that?
so after little search , tries.. below seems work. comments on how improve (or hinting why wrong), welcome! :-)
res = event.objects.raw(''' select id, sec_to_time(avg(time_to_sec(extract(hour_second happened_datetime)))) average_time_of_day event_event happened_datetime between %s , %s;''', [start_datetime, end_datetime]) print res[0].__dict__ # {'average_time_of_day': datetime.time(18, 48, 10, 247700), '_state': <django.db.models.base.modelstate object @ 0x0445b370>, 'id': 9397l}
now id returned of last object falling in datetime range clause. believe django inserts because of "invalidquery: raw query must include primary key".
quick explanation of sql series of function calls:
- extract hh:mm:ss datetime fields
- convert time values seconds via time_to_sec.
- average seconds values
- convert averaged seconds value time format (hh:mm:ss)
don't know why django insists on returning microseconds not relevant. (maybe local ms @ time object instantiated?)
performance note: seems extremely fast again haven't tested bit. insight kindly appreciated :)
Comments
Post a Comment