Python 为什么MYSQL DB在对Django models.DateTimeField进行平均时返回损坏的值?
我正在MySQL(实际上是MariaDB)数据库上运行一个Django应用程序 我的Django模型如下所示: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()
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会话的时区中计算的;