【问题标题】:Django count group by date from datetimeDjango按日期从日期时间计数组
【发布时间】:2017-08-30 08:20:42
【问题描述】:

我正在尝试计算用户从 DateTime 字段注册的日期。在数据库中,它存储为“2016-10-31 20:49:38”,但我只对日期“2016-10-31”感兴趣。

原始 SQL 查询是:

select DATE(registered_at) registered_date,count(registered_at) from User 
where course='Course 1' group by registered_date;

可以使用'extra',但我已经读过它已被弃用,不应该这样做。它的工作原理是这样的:

User.objects.all()
    .filter(course='Course 1')
    .extra(select={'registered_date': "DATE(registered_at)"})
    .values('registered_date')
    .annotate(**{'total': Count('registered_at')})

是否可以不使用额外的?

我读到可以使用 TruncDate,我认为这是正确的查询集,但它不起作用:

User.objects.all()
    .filter(course='Course 1')
    .annotate(registered_date=TruncDate('registered_at'))
    .values('registered_date')
    .annotate(**{'total': Count('registered_at')})

我收到 <QuerySet [{'total': 508346, 'registered_date': None}]>,所以 TruncDate 出了点问题。

如果有人比我更了解这一点,并能指出我正确的方向,那将不胜感激。

感谢您的帮助。

【问题讨论】:

  • 我只会使用额外的,这正是它的用途。它还没有被弃用,不要认为它会很快被弃用,而不是首先给我们一些替代解决方案,因为目前它是此类问题的唯一选择。所以我不会担心它。

标签: django date datetime django-models django-queryset


【解决方案1】:

我试图做一些非常相似的事情并且遇到了和你一样的问题。在应用TruncDate 注释后,我设法通过添加order_by 子句来解决我的问题。所以我想这也应该对你有用:

User.objects.all()
    .filter(course='Course 1')
    .annotate(registered_date=TruncDate('registered_at'))
    .order_by('registered_date')
    .values('registered_date')
    .annotate(**{'total': Count('registered_at')})

希望这有帮助吗?!

【讨论】:

    【解决方案2】:

    这是使用 `registered_at__date' 来替代使用 TruncDate 的替代方法,Django 会为您进行截断。

    from django.db.models import Count
    from django.contrib.auth import get_user_model
    
    metrics = {
        'total': Count('registered_at__date')
    }
    get_user_model().objects.all()
        .filter(course='Course 1')
        .values('registered_at__date')
        .annotate(**metrics)
        .order_by('registered_at__date')
    

    对于 Postgresql,这会转换为数据库查询:

    SELECT
        ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date,
        COUNT("auth_user"."registered_at") AS "total"
    FROM
        "auth_user"
    GROUP BY
        ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date
    ORDER BY
        ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date ASC;
    

    从上面的例子你可以看到 Django ORM 反转了 SELECTGROUP_BY 参数。在 Django ORM 中,.values() 大致控制 GROUP_BY 参数,而 .annotate() 控制 SELECT 列以及需要进行哪些聚合。这感觉有点奇怪,但是当你掌握了它的窍门后就很简单了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      • 2020-07-28
      • 2021-12-31
      相关资源
      最近更新 更多