Python 为什么MYSQL DB在对Django models.DateTimeField进行平均时返回损坏的值?

Python 为什么MYSQL DB在对Django models.DateTimeField进行平均时返回损坏的值?,python,mysql,django,django-models,mariadb,Python,Mysql,Django,Django Models,Mariadb,我正在MySQL(实际上是MariaDB)数据库上运行一个Django应用程序 我的Django模型如下所示: from django.db import models from django.db.models import Avg, Max, Min, Count class myModel(models.Model): my_string = models.CharField(max_length=32,) my_date = models.DateTimeField()

我正在MySQL(实际上是MariaDB)数据库上运行一个Django应用程序

我的Django模型如下所示:

from django.db import models
from django.db.models import Avg, Max, Min, Count

class myModel(models.Model):
    my_string = models.CharField(max_length=32,)
    my_date = models.DateTimeField()

    @staticmethod
    def get_stats():            
        logger.info(myModel.objects.values('my_string').annotate(
                count=Count("my_string"), 
                min=Min('my_date'), 
                max=Max('my_date'), 
                avg=Avg('my_date'),
            )
        )
当我运行
get_stats()
时,我会得到以下日志行:

[2015-06-21 09:45:40] INFO [all_logs:96] [{'my_string': u'A', 'count': 2, 'avg': 20080507582679.5, 'min': datetime.datetime(2007, 8, 2, 11, 33, 53, tzinfo=<UTC>), 'max': datetime.datetime(2009, 2, 13, 5, 20, 6, tzinfo=<UTC>)}]
[2015-06-21 09:45:40]信息[所有日志:96][{'my'u string':u'A','count':2,'avg':20080507582679.5,'min':datetime.datetime(2007,8,2,11,33,53,tzinfo=),'max':datetime.datetime(2009,2,13,5,20,6,tzinfo=)]
我遇到的问题是,数据库返回的my_date字段的平均值是:
20080507582679.5
。仔细看看那个数字。它是无效的日期格式

为什么数据库不返回这两个日期的平均值?如果所述方法失败,如何获得该字段的实际平均值?Django DateTimeField是否未设置为进行句柄平均?

当您使用
values()
时,Django不会转换从数据库python连接器获得的值。由连接器决定如何返回值

在本例中,MySQL连接器似乎返回了一个字符串表示,并删除了分隔符。您可以尝试使用匹配的
格式
使用
datetime.strtime()
将其解析为
datetime
对象

使用
values()
时,Django不会转换从数据库python连接器获得的值。由连接器决定如何返回值

在本例中,MySQL连接器似乎返回了一个字符串表示,并删除了分隔符。您可以尝试使用匹配的
格式
使用
datetime.strtime()
将其解析为
datetime
对象

使用
values()
时,Django不会转换从数据库python连接器获得的值。由连接器决定如何返回值

在本例中,MySQL连接器似乎返回了一个字符串表示,并删除了分隔符。您可以尝试使用匹配的
格式
使用
datetime.strtime()
将其解析为
datetime
对象

使用
values()
时,Django不会转换从数据库python连接器获得的值。由连接器决定如何返回值


在本例中,MySQL连接器似乎返回了一个字符串表示,并删除了分隔符。您可以尝试使用匹配的
格式
使用
datetime.strtime()
将其解析为
datetime
对象

计划A:使用时间戳字段而不是日期时间字段

计划B:在计算期间将DATETIME转换为时间戳:

FROM_UNIXTIME(ROUND(AVG(UNIX_TIMESTAMP(`my_date`))))

(对不起,我不知道所需的Django语法。)

计划A:使用时间戳字段而不是日期时间字段

计划B:在计算期间将DATETIME转换为时间戳:

FROM_UNIXTIME(ROUND(AVG(UNIX_TIMESTAMP(`my_date`))))

(对不起,我不知道所需的Django语法。)

计划A:使用时间戳字段而不是日期时间字段

计划B:在计算期间将DATETIME转换为时间戳:

FROM_UNIXTIME(ROUND(AVG(UNIX_TIMESTAMP(`my_date`))))

(对不起,我不知道所需的Django语法。)

计划A:使用时间戳字段而不是日期时间字段

计划B:在计算期间将DATETIME转换为时间戳:

FROM_UNIXTIME(ROUND(AVG(UNIX_TIMESTAMP(`my_date`))))

(对不起,我不知道所需的Django语法。)

Q1:为什么数据库不为这两个日期的平均值返回有效值?

A:返回的值是预期值,这是定义良好的MySQL行为

如果在数值上下文中使用日期或时间值,MySQL会自动将其转换为数值,反之亦然

MySQL参考手册:


在MySQL中,聚合函数对数值进行操作

在MySQL中,可以在数字上下文中计算日期或日期时间表达式

作为一个简单的演示,对
DATETIME
执行数字加法操作会隐式地将DATETIME值转换为数字。此查询:

  SELECT NOW(), NOW()+0
返回如下结果:

  NOW()                                NOW()+0  
  -------------------  -----------------------
  2015-06-23 17:57:48    20150623175748.000000
请注意,表达式
NOW()+0
返回的值不是
DATETIME
,而是一个数字

DATETIME
表达式上指定
SUM()
AVG()
函数时,这相当于将
DATETIME
转换为数字,然后求和 或者求平均数

也就是说,此表达式的返回值
AVG(mydatetimecol)
相当于此表达式的返回值:
AVG(mydatetimecol+0)

“平均”值是一个数值。您已经观察到,返回的值不是有效的datetime;即使在它看起来像一个有效的DATE时间的情况下,它也不一定是一个真正的“平均值”。
Q2:如果所述方法失败,如何获得该字段的实际平均值?

A2:一种方法是将日期时间转换为可以“精确”平均的数值,然后将其转换回日期时间

例如,您可以将datetime转换为表示某个固定时间点的秒数的数值,例如

  TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
然后,您可以“平均”这些值,以获得固定时间点的平均秒数。(注意:当心加起来的行数太多,值太大,超过限制(最大数值),会出现数字溢出问题。)

要将该值转换回日期时间,请将该值作为秒数添加回固定时间点:

  '2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(注意,
DATEIME
值是在MySQL会话的时区中计算的;