Django - Group by, split by date range



我有一个模型:

class MyModel(models.Model):
store_id = models.TextField()
day_dt = models.DateField()
param1 = models.IntegerField()
param2 = models.IntegerField()

一些数据示例:

store_id | day_dt     | param1 | param2
----------------------------------------
STORE1   | 2021-09-30 | 10     | 30
STORE2   | 2021-09-31 | 20     | 40
....
STORE1   | 2021-10-01 | 4      | 5
STORE1   | 2021-10-02 | 6      | 10
STORE1   | 2021-10-03 | 2      | 5
STORE2   | 2021-10-02 | 3      | 7
STORE2   | 2021-10-03 | 1      | 19
....

我需要按store_id和区间(day_dt应该在2021-10-012021-10-04之间)将数据分成组:

STORE1   | 2021-10-01
STORE1   | 2021-10-02
STORE1   | 2021-10-03

STORE2   | 2021-10-02
STORE2   | 2021-10-03 

,然后应用于每个(两个)组聚合:Avg('param1')和Avg('param2')。

数据示例的预期输出:

store_id | param1_avg | param2_avg
----------------------------------
STORE1   | 6          | 10
STORE2   | 2          | 13

我如何用ORM做这个聚合?

您可以使用:

from django.db.models import Avg
MyModel.objects.filter(
date_dt__range=('2021-10-01', '2021-10-04')
).values('store_id').annotate(
param1_avg=Avg('param1'),
param2_avg=Avg('param2')
).order_by('store_id')

这将返回一个QuerySet的字典,看起来像:

<QuerySet [
{'store_id': 'STORE1', param1_avg: 6, param2_avg: 10},
{'store_id': 'STORE2', param1_avg: 2, param2_avg: 13}
]>
在给定日期范围内没有MyModel

记录的存储将在结果查询集中有字典对象。

您可以使用这个最简单的解决方案。

但是Django的解决方案是使用表达式并编写自己的查询表达式。在这个解决方案中,创建一个类似Hours的表达式,并在annotate函数中使用它,如:.annotate(Hours("day_dt"))。您应该重写as_sql函数来编写自定义SQL方法,或者重写as_sqliteas_postgresql函数以支持不同的DBMS。

相关内容

  • 没有找到相关文章

最新更新