7

可怕的标题,但让我解释一下:我有这个 django 模型,其中包含时间戳(日期)和记录属性 - fe 消耗一些资源的用户数量 - (值)。

class Viewers(models.Model):
    date = models.DateTimeField()
    value = models.IntegerField()

对于每 10 秒,该表包含用户数。像这样的东西:

| date | value |
|------|-------|
|  t1  |   15  |
|  t2  |   18  |
|  t3  |   27  |
|  t4  |   25  |
|  ..  |   ..  |
|  t30 |   38  |
|  t31 |   36  |
|  ..  |   ..  |

现在我想从这些数据中生成不同的统计数据,每个数据都有不同的分辨率。fe 对于最后一天的图表,我不需要 10 秒的分辨率,所以我想要 5 分钟的步骤(通过平均从 t1 到 t29、t30 到 t59 的行的值(也可能是日期)来构建, ...),所以我会得到:

| date | value |
|------|-------|
|  t15 |   21  |
|  t45 |   32  |
|  ..  |   ..  |

保持变量的属性是开始和结束时间戳和分辨率(如 5 分钟)。有没有使用 django orm/queryset api 的方法,如果没有,如何使用自定义 sql 来实现?

4

4 回答 4

4

我一直在尝试以最“django”的方式解决这个问题。我已经解决了以下问题。它对 start_date 和 end_date 之间的 15 分钟时间段的值进行平均,其中列名是“日期”:

readings = Reading.objects.filter(date__range=(start_date, end_date)) \
   .extra(select={'date_slice': "FLOOR (EXTRACT (EPOCH FROM date) / '900' )"}) \
   .values('date_slice') \
   .annotate(value_avg=Avg('value'))

它返回一个字典:

 {'value_avg': 1116.4925373134329, 'date_slice': 1546512.0}
 {'value_avg': 1001.2028985507246, 'date_slice': 1546513.0}
 {'value_avg': 1180.6285714285714, 'date_slice': 1546514.0}

这个想法的核心来自这个对 PHP/SQL 相同问题的回答。传递给 extra 的代码用于 Postgres 数据库。

于 2014-02-12T23:06:36.680 回答
2
from django.db.models import Avg

Viewers.objects.filter(date__range=(start_time, end_time)).aggregate(average=Avg('value'))

这将为您提供所有values介于start_time和之间的平均值,end_time以 的形式作为字典返回{ 'average': <the average> }

start_time并且end_time需要是 Python 日期时间对象。因此,如果您有时间戳或其他内容,则需要先对其进行转换。您还可以使用基于 start_timedatetime.timedelta来计算。end_time对于五分钟的解决方案,如下所示:

from datetime import timedelta

end_time = start_time + timedelta(minutes=5)
于 2011-06-07T15:02:39.910 回答
1

你看过范围过滤器吗?

https://docs.djangoproject.com/en/dev/ref/models/querysets/#range

文档中给出的示例似乎与您的情况相似。

于 2011-06-07T14:50:10.723 回答
-1

经过长时间的尝试,我将其作为 SQL 语句:

SELECT FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(date))), SUM(value)
FROM `my_table`
WHERE date BETWEEN SUBTIME(NOW( ), '0:30:00') AND NOW()
GROUP BY UNIX_TIMESTAMP(date) DIV 300
ORDER BY date DESC

start_time = SUBTIME(NOW( ), '0:30:00')
end_time = NOW()
period = 300 # in seconds

最后 - 不是真的很难 - 并且确实独立于原始表中采样的时间分辨率。

于 2011-06-08T07:03:07.900 回答