gpt4 book ai didi

python - 从查询集中构建最高价格列表的最有效方法?

转载 作者:可可西里 更新时间:2023-11-01 07:38:44 24 4
gpt4 key购买 nike

在我的应用程序的一页中,我试图显示每家公司最昂贵的汽车。我的模型大致如下所示:

class Company(models.Model):
id = models.IntegerField(primary_key=True)
company = models.CharField(max_length=100)
headcount = models.IntegerField(null=False)
info = models.CharField(max_length=100)

class Car(models.Model):
id = models.IntegerField(primary_key=True)
company_unique = models.ForeignKey(Company)
company = models.CharField(max_length=50)
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=9, decimal_places=2, default=0.00)

因此,我想构建一个列表,其中包含每家公司的单个最昂贵的 Car 对象。

我是这样处理问题的:

company_list = Company.objects.all()
most_expensive = []
for company in company_list:
most_expensive.append(Car.objects.filter(company_unique=company.id).order_by("-price")[0])

但是,这似乎是一种非常低效的方法。我可以通过 Django 调试工具栏看到这段代码产生了太多的 mysql 查询。

有人可以建议一种更好的方法来构建此列表,该列表可能只会攻击 MySQL 一两次吗?

最佳答案

虽然您正在处理的是一个很常见的案例,但似乎缺乏一个明显的解决方案。

解决方案 1,在 this article 中找到.您或许可以尝试以下方法:

companies = Company.objects.annotate(max_price=Max('car__price'))
values = tuple((company.id, company.max_price) for company in companies)

expensive_cars = Car.objects.extra(where=['(company_unique_id, price) IN %s' % (values,)])

不能说我喜欢这个解决方案 - 应该避免使用 .extra - 但我想不出更好的方法。我也不完全确定这是否有效。

解决方案 2,次优。您可以使用 custom Prefetch object .

prefetch = Prefetch('cars', queryset=Car.objects.order_by('-price'), to_attr='cars_by_price')
companies = Company.objects.prefetch_related(prefetch)

most_expensive_cars = []
for company in companies:
most_expensive_cars.append(list(company.cars_by_price.all())[0])

这应该确实有效并在两个查询中获取所有内容,但是非常浪费,因为它会将与给定的一组 Companies 相关的所有 Cars 加载到内存中。请注意 list() 部分不是可选的:无论您在何处使用切片或索引,都会复制查询集并生成单独的数据库查询,因此否定预取,而实例化列表将使用结果所述预取。

如果您之后需要访问公司,例如 Car.company,请不要回避使用 select_related,正如 Erik 在评论中所建议的那样。

关于python - 从查询集中构建最高价格列表的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40849966/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com