Django聚合目标

时间:2014-03-28 23:42:23

标签: python django django-orm

我在商店中保存每件商品。我希望使用聚合来汇总每个商店一个月内的所有销售额。我想过滤达到目标的商店(100.000 $)。

我已经提出了使用python和列表的解决方案。但我想知道是否有更好的解决方案只使用ORM。

Sales model

Store        Sale     Date
Store A      5.000    11/01/2014
Store A      3.000    11/01/2014
Store B      1.000    15/01/2014
Store C      8.000    17/01/2014
...

结果应该是这样的:

Month: January

Store   Amount
A       120.000
B       111.000
C       150.000

and discard
D        70.000

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

其他建议的方法会丢弃大量需要几分之一秒加载的数据,这在以后的代码中可能会有用。因此这个答案。

您可以查询Sales对象,而不是查询Store对象。除了关系之外,查询大致相同:

from django.db.models import Sum

stores = Store.objects.filter(sales__date__month=month, sales__date__year=year) \
    .annotate(montly_sales=Sum('sales__amount')) \
    .filter(montly_sales__gte=100000) \
    # optionally prefetch all `sales` objects if you know you need them
    .prefetch_related('sales') 

>>> [s for s in stores]
[
    <Store object 1>,
    <Store object 2>,
    etc.
]

所有Store个对象都有一个额外的属性montly_sales,该属性具有该特定月份的总销售额。通过在注释之前过滤月份和年份,注释仅使用过滤的相关对象。请注意,商店中的sales属性仍包含该商店的所有销售额。

使用此方法,您可以轻松访问所有商店属性,这与使用.values对结果进行分组时不同。

答案 1 :(得分:2)

如果没有好好看看你的模型,我能做的最好的就是伪代码。但我希望你需要的东西是

from django.db.models import Sum
results = Sales.objects.filter(date__month=month, date__year=year)
results = results.values('store')
results = results.annotate(total_sales=Sum(sale))
return    results.filter(total_sales__gt=100)

基本上,我们正在做的是使用django的聚合功能来计算每个商店的销售总额。根据django&#39; documentation,我们可以使用values函数按给定字段中的不同值对结果进行分组。

  • 在第2行,我们将销售额过滤到本月的销售额。
  • 在第3行中,我们将结果限制为字段存储的值。
  • 在第4行中,我们使用来自的所有销售额的总和来注释每个结果 原始查询。
  • 在第5行中,我们过滤了该注释,将返回的结果限制为total_sales大于100的商店。

答案 2 :(得分:0)

您可以使用annotate来处理此问题。由于我不知道你的模型结构,这是一个平均猜测

from djnago.db.models import Sum
Sales.objects.filter(date__month=3, date__year=2014).values('store').annotate(monthly_sale=Sum('sale'))

这将返回一个商店的查询集及其月销售额,如:

>> [
    {"store": 1, "monthly_sale": 120.000},
    {"store": 2, "monthly_sale": 100.000},
    ...
]

在上面的查询中假设你有:

  • 销售模型包含名为Date
  • Datetimedate字段
  • 您的Sale模型与Store
  • 有ForeignKey关系
  • 您的Sales模型有一个名为Integer
  • 的数字字段(Decimalsale等)

在生成的QuerySet中,store是商店记录的ID。但由于它是ForeigKey,你可以使用关系来获取它的名字......

Sales.objects.filter(date__month=3, date__year=2014).values('store__name').annotate(monthly_sale=Sum('sale'))


>> [
    {"store__name": "Store A", "monthly_sale": 120.000},
    {"store__name": "Store B", "monthly_sale": 100.000},
    ...
]