How to write a Django QuerySet the properly computes average of DateTimeField with grouping?

人盡茶涼 提交于 2019-12-06 08:23:51

Instead of using the Django ORM, you could use a raw sql query.

from django.db import connection
query = """
SELECT `a`,
       COUNT(b) AS `count`,
       MAX(b) AS `max`,
       AVG(UNIX_TIMESTAMP(b)) AS `avg`,
       MIN(b) AS `min`
FROM `<appname>_<modelname>`
GROUP BY `a`
"""
cursor = connection.cursor()
cursor.execute(query)
result = cursor.fetchall()

This will give you something like:

(
    (a value1, count, max, avg as unix timestamp, min), ...
    (a value2, count, max, avg as unix timestamp, min), ...
    (a value3, count, max, avg as unix timestamp, min), ...
)

Otherwise, the closest thing I could get using Django's ORM would be to abandon the UNIX_TIMESTAMP conversion in the extra clause:

from django.db.models import Count, Min, Max, Avg
MyModel.objects.all().values('a').annotate(
    count=Count('b'), 
    max=Max('b'), 
    avg=Avg('b'), 
    min=Min('b')
)

Unfortunately, this will give you the average as a float.

[
    {
        'count': 15366, 
         'a': 0, 
         'avg': 19898862327498.82, 
         'min': datetime.datetime(1900, 1, 1, 0, 0), 
         'max': datetime.datetime(2012, 7, 3, 0, 0)
    }, {
         'count': 1726, 
         'a': 1, 
         'avg': 19785827400927.0, 
         'min': datetime.datetime(1920, 8, 25, 0, 0), 
         'max': datetime.datetime(1994, 12, 29, 0, 0)
    }, 
    ...

]

You can try using something like

import datetime
datetime.datetime.strptime(str(int(ts)), '%Y%m%d%H%M%S%f')

to convert it back to a datetime object, though this will be an approximation, so I recommend using raw sql instead.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!