首页 > 解决方案 > Django Query group_by datetime 包含重复的日期数据

问题描述

嗨,我一直在尝试调试我的 Django 查询出了什么问题,但我仍然无法弄清楚。我有一个名为“Ticket”的模型,它有一个名为“created”的字段,它是一个日期时间字段。我正在尝试返回一个对象数组,其中包含在给定日期范围(从和到)内为每个唯一日期(yyyy-mm-dd)创建的票数,但我得到 1 个重复的日期,这很奇怪。请查看下面的结果和我的代码。日期“2021-02-08”有 1 个重复,而其他都是正确的。当我检查数据库时,“2021-02-08”的计数确实有超过 20 行,我假设保存的日期时间不知道时区。我还将我的 Django 项目的时区配置为“亚洲/马尼拉”。我还继承了 Ticket 模型的 TimeStampedModel,它会自动填充“created”和“modified”字段。(https://django-model-utils.readthedocs.io/en/latest/models.html

以 JSON 格式返回的数据:

"activation_chart_data": [
    {
        "date": "2021-02-08",
        "count": 20
    },
    {
        "date": "2021-02-08",
        "count": 31
    },
    {
        "date": "2021-02-09",
        "count": 32
    },
    {
        "date": "2021-02-11",
        "count": 15
    },
    {
        "date": "2021-02-12",
        "count": 51
    },
    {
        "date": "2021-02-15",
        "count": 1
    },
    {
        "date": "2021-02-16",
        "count": 4
    },
    {
        "date": "2021-02-18",
        "count": 15
    },
    {
        "date": "2021-02-23",
        "count": 5
    }
]

Django 查询:

Ticket.objects.filter(Q(created__gte=from_date) & Q(
            created__lte=end_date) & Q(type__slug='activation-code')).extra(select={'date': 'date(shop_ticket.created)'}).order_by('created__date').values('date').annotate(count=Count('created'))

正在执行的原始 Postgre SQL 查询:

SELECT (date(shop_ticket.created)) AS "date", COUNT("shop_ticket"."created") AS "count" FROM "shop_ticket" INNER JOIN "shop_tickettype" ON ("shop_ticket"."type_id" = "shop_tickettype"."id") WHERE ("shop_ticket"."created" >= 2021-03-01 00:00:00+08:00 AND "shop_ticket"."created" <= 2021-03-09 00:00:00+08:00 AND "shop_tickettype"."slug" = activation-code) GROUP BY (date(shop_ticket.created)), ("shop_ticket"."created" AT TIME ZONE 'Asia/Manila')::date ORDER BY ("shop_ticket"."created" AT TIME ZONE 'Asia/Manila')::date ASC

标签: pythondjangopostgresqldjango-orm

解决方案


尝试添加distinct=true计数

Ticket.objects.filter(
    Q(created__gte=from_date) &
    Q(created__lte=end_date) &
    Q(type__slug='activation-code')
).extra(
    select={'date': 'date(shop_ticket.created)'}
).order_by('created__date').values('date').annotate(
    count=Count('created', distinct=True)
)

推荐阅读