Django - 分组依据,按日期范围分割

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<strong>.filter(</strong>
    date_dt__range=('2021-10-01', '2021-10-04')
<strong>).values(</strong>'store_id'<strong>).annotate(</strong>
    param1_avg=Avg('param1'),
    param2_avg=Avg('param2')
<strong>).order_by(</strong>'store_id'<strong>)</strong>

这将 return 一个 QuerySet 字典,看起来像:

<QuerySet [
    {'store_id': 'STORE1', param1_avg: 6, param2_avg: 10},
    {'store_id': 'STORE2', param1_avg: 2, param2_avg: 13}
]>

在给定日期范围内没有 MyModel 记录的商店将 不会 在生成的查询集中有字典对象。

您可以使用,这是最简单的方法。

但是 Django 解决方案使用的是 Expression 和 writing your own Query Expressions。在此解决方案中,您创建了一个类似于 Hours 的表达式,并在 annotate 函数中使用它,例如:.annotate(Hours("day_dt"))。您应该覆盖 as_sql 函数来编写自定义 SQL 方法,或者覆盖 as_sqliteas_postgresql 函数以支持不同的 DBMS。