【问题标题】:Django query - get first x elements which together exceed a specific amount for a fieldDjango 查询 - 获取第一个 x 元素,它们一起超过字段的特定数量
【发布时间】:2018-04-01 08:57:57
【问题描述】:

我想请求一起超过特定数量的前 x 个元素,我不知道这是否可能。 所以假设这是我的模型:

class Article(models.Model):
     price = models.DecimalField(default=0.0, max_digits=7, decimal_places=2)

现在,如果我通过price 订购Articles,我想要第一个Articles,它们加起来超过price,比如说100 美元。 这是否可以通过注释、求和、extra() 或其他方式实现?

Article.objects.order_by("price")

例如: 我有 3 篇文章:

Article1 (price=50 Dollar)
Article2 (price=60 Dollar)
Article3 (price=20 Dollar)

....现在我想要价格超过 100 美元的文章...所以这将是 Article1 和 Article2。加起来价值 110 美元

原始 sql 语句中的这个答案会欺骗他,但我不知道如何用 django 语法解决这个问题 limiting the rows to where the sum a column equals a certain value in MySQL

【问题讨论】:

  • 前x个元素怎么说?先创建?
  • 假设我有 3 篇文章:文章 1(价格=50 美元)文章 2(价格=60 美元)和文章 3(价格=20 美元)....现在我想要这些文章一起超过 100 美元的价格...所以这将是第 1 条和第 2 条。加起来价值 110 美元
  • 如果不使用 forloop,我什么都想不出来。
  • 我在原始 sql 中找到了答案:stackoverflow.com/questions/14890486/… 但是这如何使用 Django 语法? :)

标签: sql django django-queryset


【解决方案1】:

我认为您无法仅通过数据库查询来做到这一点。您链接到的 SQL 问题的答案需要存储过程,或者非常昂贵 (O(N^2))。

您可以使用高效运行的迭代器查询来实现相同的目的,并且需要在 Python 中进行非常简单的操作。像这样的:

articles = Article.objects.order_by("price").iterator()
to_update = []
total = 0
for article in articles:
    total += article.price
    if total > 100:
        break
    to_update.append(article.pk)

# Select the affected objects for update
Article.objects.select_for_update().filter(pk__in=to_update)

因为您使用的是iterator(),所以您只会从数据库中获取您需要的项目。

【讨论】:

  • 这是怎么回事:Article.objects.annotate(total_price=Sum(‚price‘)).filter(total_price__lte=100) ?我想我会试试这个
  • 试一试...我不确定它是否有效,如果有效,它将是 O(N^2),比迭代更昂贵。
  • 问题是我需要做一个 select_for_update ,这只是可能的查询集:/
  • 你仍然可以做到这一点,有点 - 我已经编辑了我的答案来展示如何。您唯一的其他选择 IMO 是使用原始 SQL。
  • 好吧,这是一种可能性,但是如果在迭代另一个线程期间更改了文章的价格怎么办?这是个问题
猜你喜欢
  • 2013-12-29
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多