我有一个正在做日志记录的django应用程序.我的模型看起来像这样:
class MessageLog(models.Model):
logtime = models.DateTimeField(auto_now_add=True)
user = models.CharField(max_length=50)
message = models.CharField(max_length=512)
Run Code Online (Sandbox Code Playgroud)
想要做的是获取一周中每天记录的平均消息数,以便我可以看到哪些天最活跃.我设法写了一个查询,每天提取的邮件总数是:
for i in range(1, 8):
MessageLog.objects.filter(logtime__week_day=i).count()
Run Code Online (Sandbox Code Playgroud)
但是我在查询中计算平均值时遇到了麻烦.我现在拥有的是:
for i in range(1, 8):
MessageLog.objects.filter(logtime__week_day=i).annotate(num_msgs=Count('id')).aggregate(Avg('num_msgs'))
Run Code Online (Sandbox Code Playgroud)
出于某种原因,这是每天返回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
Run Code Online (Sandbox Code Playgroud)
我认为问题可能来自GROUP BY id,但我不太确定.任何人有任何想法或建议吗?提前致谢!
Pet*_*per 10
列出的查询总是给出1的原因是因为您没有按日期分组.基本上,您已经要求数据库获取MessageLog
一周中给定日期的行.对于每个这样的行,计算它有多少个ID(总是1).然后取所有这些计数的平均值,当然也是1.
通常,您需要使用一个values
子句MessageLog
在您annotate
和aggregate
部件之前对行进行分组.但是,由于您的logtime
字段是日期时间而不仅仅是日期,我不确定您是否可以直接使用Django的ORM表达.你绝对可以用做extra
从句,如图所示这里.或者,如果你觉得你可以在你的SQL中声明一个你喜欢的聚合和平均数学的视图,并为它声明一个非托管模型,那么只需正常使用ORM.
因此,extra
字段用于获取每个实际日期的记录总数,但不处理聚合计算注释的平均值.我认为这可能是从您必须使用原始SQL查询的模型中充分抽象出来的,或者至少我找不到任何使它在一次调用中工作的东西.
也就是说,您已经知道如何在一个简单的查询中获得每个工作日的记录总数,如问题所示.
此查询将告诉您给定工作日有多少不同的日期记录:
MessageLog.objects.filter(logtime__week_day=i).dates('logtime', day').count()
Run Code Online (Sandbox Code Playgroud)
因此,您可以在Python中进行平均数学运算,这可能比尝试正确使用SQL更简单.
或者,此查询将在一个查询中获取所有工作日的原始消息数,而不是for循环:
MessageLog.objects.extra({'weekday': "dayofweek(logtime)"}).values('weekday').annotate(Count('id'))
Run Code Online (Sandbox Code Playgroud)
但是我无法得到一个很好的查询来给你每个工作日注释的不同日期的计数 - 日期查询集失去了处理注释调用的能力,并且对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'))
Run Code Online (Sandbox Code Playgroud)
以上将按“created_at”字段中日期时间值的日期分组。
归档时间: |
|
查看次数: |
7886 次 |
最近记录: |