Django 按权重分组并聚合

Django group by and aggregate with weights

我有一个这样的 table,我使用 Django ORM 进行交互。

date                car_crashes         city
01.01               1                   Washington
01.02               4                   Washington
01.03               0                   Washington
01.04               2                   Washington
01.05               0                   Washington
01.06               3                   Washington
01.07               4                   Washington
01.08               1                   Washington
01.01               0                   Detroit
01.02               2                   Detroit
01.03               4                   Detroit
01.04               2                   Detroit
01.05               0                   Detroit
01.06               3                   Detroit
01.07               1                   Detroit

我想知道全国每天发生多少起车祸,我可以这样做:

Model.values("date") \
.annotate(car_crashes=Sum('car_crashes')) \
.values("date", "car_crashes")

date  car_crashes
1.01            1
1.02            6
1.03            4
1.04            4
1.05            0
1.06            6
1.07            5
1.08            1

现在,假设我有一个这样的数组:

weights = [
    {
        "city": "Washington",
        "weight": 1,
    },
    {
        "city": "Detroit",
        "weight": 2,
    }
]

这意味着底特律的车祸应该乘以 2,然后才能与华盛顿的相加。

我的解决方案是分别聚合所有不同的权重,乘以 Pandas 或 SQL 的权重,然后进行聚合。这将是低效且缓慢的(充其量是许多查询,最坏的情况是使用 Pandas)。

是否可以通过单个 ORM 查询或 SQL 查询来实现?

一种方法是使用Conditional Expressions来确定查询中的权重值,这意味着您可以先构造Case表达式:

from django.db.models import IntegerField

when_list = [When(city=w['city'], then=w['weight']) for w in weights]
case_params = {'default': 1, 'output_field': IntegerField()}

Model.objects.values('date') \
    .annotate(
        weighted_car_crashes=Sum(
            F('car_crashes') * Case(*when_list, **case_params)
    ))