我有一张看起来像这样的桌子
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
Run Code Online (Sandbox Code Playgroud)
我想知道全国每天发生多少次车祸,我可以用这个来做:
Model.values("date") \
.annotate(car_crashes=Sum('car_crashes')) \
.values("date", "car_crashes")
Run Code Online (Sandbox Code Playgroud)
现在,让我们假设我有一个这样的数组:
weights = [
{
"city": "Washington",
"weight": 1,
},
{
"city": "Detroit",
"weight": 2,
}
]
Run Code Online (Sandbox Code Playgroud)
这意味着底特律的车祸应乘以 2,然后再与华盛顿的相加。
可以这样做:
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)
))
Run Code Online (Sandbox Code Playgroud)
但是,这会生成非常慢的 SQL 代码,尤其是在引入更多属性和更大数组时。
另一个更快但仍然次优的解决方案是使用熊猫:
aggregated = false
for weight in weights:
ag = Model.filter(city=w[‘city’]).values("date") \
.annotate(car_crashes=Sum('car_crashes') * w[‘weight’]) \
.values("date", "car_crashes")
if aggregated is False:
aggregated = ag
else:
aggregated = aggregated.union(ag)
aggregated = pd.DataFrame(aggregated)
if len(weights) > 1:
aggregated = aggregated.groupby("date", as_index=False).sum(level=[1])
Run Code Online (Sandbox Code Playgroud)
这更快,但仍然不如在调用 pandas 之前,我获取aggregated.query字符串并用几行 SQL 将其包装时发生的速度快。
SELECT "date", sum("car_crashes") FROM (
// String from Python
str(aggregated.query)
) as "foo" GROUP BY "date"
Run Code Online (Sandbox Code Playgroud)
这在粘贴到我的数据库 SQL 中时非常有效。我可以在 Python/Django 中使用,.raw()但文档说在使用之前要询问,.raw()因为大多数东西都可以用 ORM 完成。
然而,我不明白如何。一旦我调用.union()了 2 个查询集,我就无法进一步聚合。
aggregated.union(ag).annotate(cc=Sum('car_crashes'))
Run Code Online (Sandbox Code Playgroud)
给
无法计算 Sum('car_crashes'): 'car_crashes' 是一个聚合
这可能与Django ORM有关还是我应该使用.raw()?
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |