繁体   English   中英

Django每天汇总记录数

[英]Django aggregate count of records per day

我有一个 django 应用程序正在做一些日志记录。 我的模型看起来像这样:

class MessageLog(models.Model):
    logtime = models.DateTimeField(auto_now_add=True)
    user = models.CharField(max_length=50)
    message = models.CharField(max_length=512)

想要做的是获取一周中每天记录的平均消息数,以便我可以查看哪些天是最活跃的。 我设法编写了一个查询来提取每天的消息总数,即:

for i in range(1, 8):
    MessageLog.objects.filter(logtime__week_day=i).count()

但是我在计算查询中的平均值时遇到了问题。 我现在拥有的是:

for i in range(1, 8):
    MessageLog.objects.filter(logtime__week_day=i).annotate(num_msgs=Count('id')).aggregate(Avg('num_msgs'))

出于某种原因,这每天都会返回 1.0。 我查看了它生成的 SQL,它是:

SELECT AVG(num_msgs) FROM (
SELECT 
`myapp_messagelog`.`id` AS `id`, `myapp_messagelog`.`logtime` AS `logtime`, 
`myapp_messagelog`.`user` AS `user`, `myapp_messagelog`.`message` AS `message`, 
COUNT(`myapp_messagelog`.`id`) AS `num_msgs` 
FROM `myapp_messagelog` 
WHERE DAYOFWEEK(`myapp_messagelog`.`logtime`) = 1 
GROUP BY `myapp_messagelog`.`id` ORDER BY NULL
) subquery

我认为问题可能来自 GROUP BY id,但我不确定。 任何人有任何想法或建议? 提前致谢!

您列出的查询总是给出 1 的原因是因为您没有按日期分组。 基本上,您已经要求数据库获取一周中给定日期的MessageLog行。 对于每个这样的行,计算它有多少个 id(总是 1)。 然后取所有这些计数的平均值,这当然也是 1。

通常,您需要使用values子句在annotateaggregate部分之前对MessageLog行进行分组。 但是,由于您的logtime字段是日期时间而不仅仅是日期,我不确定您是否可以直接用 Django 的 ORM 来表达。 你绝对可以用做extra条款,如在这里 或者,如果您愿意,您可以在您的 SQL 中声明一个包含尽可能多的聚合和平均数学的视图,并为其声明一个非托管模型,然后正常使用 ORM。

因此, extra字段可用于获取实际每天的记录总数,但不处理聚合计算注释的平均值。 我认为这可能是从模型中充分抽象出来的,您必须使用原始 SQL 查询,或者至少我找不到任何使它在一次调用中工作的东西。

也就是说,您已经知道如何在简单查询中获取每个工作日的记录总数,如您的问题所示。

这个查询会告诉你在给定的工作日有多少不同的日期记录:

MessageLog.objects.filter(logtime__week_day=i).dates('logtime', day').count()

因此,您可以在 Python 中进行平均数学运算,这可能比尝试正确获取 SQL 更简单。

或者,此查询将在一个查询而不是 for 循环中为您提供所有工作日的原始消息数:

MessageLog.objects.extra({'weekday': "dayofweek(logtime)"}).values('weekday').annotate(Count('id'))

但是我无法得到一个很好的查询来为您提供注释的每个工作日的不同日期的计数 - 日期查询集失去了处理注释调用的能力,并且注释一个extra值似乎也不起作用.

鉴于 SQL 表达式并不难,这出奇地棘手。

我对日期时间字段做了类似的事情,但对额外值进行注释对我有用。 我有一个记录模型,它有一个日期时间字段“created_at”和一个“my_value”字段,我想获得平均值。

from django.db.models import Avg

qs = Record.objects.extra({'created_day':"date(created_at)"}).\
    values('created_day').\
    annotate(count=Avg('my_value'))

以上将按“created_at”字段中日期时间值的日期分组。

queryset.extra(select={'day': 'date(logtime)'}).values('day').order_by('-day').annotate(Count('id'))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM