Python 用一个值标注每个结果,该值指示字段的最小值还是最大值
我有两个模型,Python 用一个值标注每个结果,该值指示字段的最小值还是最大值,python,django,database,query-optimization,Python,Django,Database,Query Optimization,我有两个模型,作者和书籍: class Author(models.Model): name = models.CharField(max_length=256) class Book(models.Model): name = models.CharField(max_length=256) price = models.IntegerField() publication_date = models.DateField() author = mode
作者
和书籍
:
class Author(models.Model):
name = models.CharField(max_length=256)
class Book(models.Model):
name = models.CharField(max_length=256)
price = models.IntegerField()
publication_date = models.DateField()
author = models.ForeignKey(Author, related_name="books")
现在,当我得到一组作者和他们的书时,我想用两个值对每本书进行注释,指示它是同一作者筛选出的书中最便宜的还是最贵的
我使用Exists
和注释得到了正确的结果
filtered_books = Book.objects.filter(publication_date__year=2010)
lower_price = filtered_books.only('id').filter(price__lt=OuterRef('price'), author=OuterRef('author'))
higher_price = filtered_books.only('id').filter(price__gt=OuterRef('price'), author=OuterRef('author'))
filtered_books = filtered_books.annotate(
lowest_price=~Exists(lower_price),
highest_price=~Exists(higher_price),
)
authors = Author.objects.annotate.prefetch_related(Prefetch('books', queryset=filtered_books))
它可以工作,但会导致执行三个非常相似的子查询(lower_price
,higher_price
和预取),而且速度不是很快。我如何优化它
现在,当我得到一组作者和他们的书时,我想要注释
每本书有两个值,表示它是最便宜的还是最便宜的
从同一作者的筛选出的书籍中提取
它可以工作,但会产生三种结果(较低的价格、较高的价格和
预取)执行非常相似的子查询,速度并没有那么快。
我如何优化它
- 你无法逃避这3个问题,它们总是会被呈现出来 以这样或那样的形式
- 拥有3个类似的查询并不意味着它们的速度比单个查询慢3倍,这需要更多的调查才能找到瓶颈所在,可能是缺少索引或smt
- 指出一本书是最便宜的还是最贵的意味着您需要将书的价格与一些最低/最高价格进行比较。一旦有了这个最小/最大价格,比较就很容易了。由于您希望将本书与作者在queryset中的其他书进行比较,因此在Authors queryset中进行比较更有意义。例如:
filtered_books = Book.objects.filter(publication_date__year=2010) min_price_subquery = (filtered_books .filter(author=OuterRef('pk')) .values('author') .annotate(min_price=Min('price')) .only('min_price') ) max_price_subquery = (filtered_books .filter(author=OuterRef('pk')) .values('author') .annotate(max_price=Max('price')) .only('max_price') ) authors = Author.objects.annotate( min_book_price=Subquery(min_price_subquery, output_field=models.IntegerField()), max_book_price=Subquery(max_price_subquery, output_field=models.IntegerField()) ).prefetch_related(Prefetch('books', queryset=filtered_books)) for author in authors: for book in author.books: if book.price == author.min_book_price: #cheapest price if book.price == author.max_book_price: #most expensive