首页 > 解决方案 > Django ORM 在 15 分钟的时间块内获取数据的平均值

问题描述

我每 30 秒抓取一次数据并将其存储在此模型中。

class Frequency(models.Model):
    """Store the frequency  scraped"""
    timestamp = models.DateTimeField()
    frequency = models.DecimalField(max_digits=5, decimal_places=2)

现在我被分配了一项任务,每天每 15 分钟我必须对结果进行平均并分组为 08:15-08:30、08:30-08:45 .... 23:45- 24:00。

我想的是使用两个循环。外层将在一天中的几个小时内循环,而内层将在 (00, 15, 30, 45) 中循环,然后更改今天的 datetime.now() 并对其进行过滤。

有没有更好的方法或者这很好?

标签: djangodjango-modelsdjango-orm

解决方案


通过对每个时间跨度进行独立过滤,您将每天进行 24*4 的数据库查询,这对于如此简单的操作来说已经很多了。要在一个查询中进行,您可以注释您的查询frequencies集并closest_quarter_of_hour为每个对象设置。然后,您可以使用 Django方法获取平均频率aggregate并创建一个 SQL子句。group byvalues

from django.db.models import CharField, Case, When, Q, Value, Avg
from django.db.models.functions import ExtractHour, ExtractMinute

today = timezone.now().date()
frequencies = Frequency.objects.filter(timestamp__date=today).annotate(
    hour=ExtractHour("timestamp"),
    minute=ExtractMinute("timestamp"),
).annotate(
    closest_quarter_of_hour=Case(
        When(minute__gte=0, minute__lt=15, then=Value('00-15')),
        When(minute__gte=15, minute__lt=30, then=Value('15-30')),
        When(minute__gte=30, minute__lt=45, then=Value('30-45')),
        When(minute__gte=45, then=Value('45-00')),
        output_field=CharField(),
    )
).aggregate(Avg("frequency")).values("hour", "closeset_quarter_of_hour")

结果:在一个 SQL 查询中完成的每 15 分钟时间跨度的平均频率。


推荐阅读