【问题标题】:Django Query to Aggregate the Sum for Matching Instances in the Same FieldDjango 查询聚合相同字段中匹配实例的总和
【发布时间】:2018-09-14 20:57:08
【问题描述】:

我有以下 Django (2.1) 模型:

class Sales(models.Model):
    product_name = models.ForeignKey(Product)
    category = models.ForeignKey(Category)
    sales= models.DecimalField(max_digits=25)

我想收到每个相同的product_name 实例的所有销售额的总和。

例如,我有以下product_name 的销售额:

  • DVD = 6.00
  • DVD = 6.00
  • 书籍 = 14.00
  • 书籍 = 6.00
  • 杂志 = 4.00
  • 杂志 = 4.00

我可以使用Sales.objects.aggregate(sales=Sum('sales')) 来获取所有销售实例的总聚合,但我如何分别获取product_name 的聚合;即书籍(20.00 美元)、DVD(12.00 美元)、杂志(8.00 美元)?

【问题讨论】:

    标签: python django


    【解决方案1】:

    我们可以将.annotate.values 结合使用:

    Sales.objects.values(
        'product_name'
    ).annotate(
        total_sales=Sum('sales')
    ).order_by('product_name')

    注意product_nameForeignKey,所以我们会得到Product对象的id,比如:

    <QuerySet [
        {'product_name': 1, 'total_sales': 12.00 },
        {'product_name': 2, 'total_sales': 20.00 },
        {'product_name': 3, 'total_sales': 8.00 } ]>
    

    因此,我认为您可能对使用 Product 对象进行查询更感兴趣,例如:

    Product,objects.values(
        'name'
    ).annotate(
        total_sales=Sum('sales__sales')
    ).order_by('name')
    

    然后产生:

    <QuerySet [
        {'name': 'Books', 'total_sales': 20.00 },
        {'name': 'DVDs', 'total_sales': 12.00 },
        {'name': 'Magazines', 'total_sales': 8.00 } ]>
    

    因此这些是包含字典的QuerySets:每个字典都有两个键:'name'total_sales',因此我们可以遍历字典并处理键值对。

    我们使用total_sales,因为我的经验是,将聚合命名为与另一个字段相同通常会导致一些问题。首先,并不清楚这与sales 字段是否不同。此外,在某些版本的 Django 中,这可能会导致无效查询。

    注意:因为ForeignKey 指的是相关模型的对象。我建议将 product_name 重命名为 product

    【讨论】:

    • 谢谢,威廉!谢谢你的回答——这正是我所需要的。我也感谢您的建议。
    猜你喜欢
    • 2018-02-03
    • 2012-08-23
    • 1970-01-01
    • 2018-10-03
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    相关资源
    最近更新 更多