簡體   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