You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中MySQL按DateTime字段日期分组聚合求和异常问题

Django按日期分组求和:SQLite正常但MySQL返回异常结果

模型定义

class Data(models.Model):
    created_at = models.DateTimeField(default=timezone.now)
    number = models.IntegerField(default=1)

需求

提取created_at字段的日期部分进行分组,计算每组number字段的总和。

测试代码

qs = Data.objects.values('created_at__date').annotate(sum=Sum('number'))

问题表现

上述查询在SQLite环境中运行正常,但在MySQL中执行后返回错误结果:

<QuerySet [{'created_at__date': None, 'sum': 100}]>

期望结果

<QuerySet [
  {'created_at__date': datetime.date(2021, 7, 12), 'sum': 50}, 
  {'created_at__date': datetime.date(2021, 7, 13), 'sum': 50}
]>

解决办法

方法1:使用TruncDate显式截断日期

Django的TruncDate函数能正确处理时区转换,确保MySQL可以识别分组字段:

from django.db.models.functions import TruncDate

qs = Data.objects.annotate(created_date=TruncDate('created_at'))\
                  .values('created_date')\
                  .annotate(sum=Sum('number'))\
                  .order_by('created_date')

通过先将created_at截断为日期字段created_date,再以此字段分组求和,能避免MySQL对隐式日期转换的处理差异。

方法2:配置MySQL连接时区

如果Django启用了时区(USE_TZ = True),需确保MySQL连接的时区和Django配置一致。在settings.py的数据库配置中添加时区参数:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '你的数据库名',
        'USER': '用户名',
        'PASSWORD': '密码',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES', time_zone='+00:00'",
        },
    }
}

这里的time_zone值要和Django的TIME_ZONE设置匹配,比如Django用UTC就设为+00:00,如果用Asia/Shanghai,需确保MySQL已加载对应时区数据,可设置为'+08:00'或'Asia/Shanghai'。

内容的提问来源于stack exchange,提问作者Mas Zero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 11:10:42