我很难绕过这个Django查询。我可能用SQL来解决这个问题(也许我不得不这样做),但我想知道是否有办法用Django对象来做。
模型看起来像这样(为了清晰起见,简化了):
class Stat(model.Models):
entry_date = models.DateTimeField()
quantity = models.PositiveIntegerField()
user = models.ForeignKey(User)
我需要返回用户按月分组的所有最近添加的数量的总和(使用注释和求和,我猜)。这有点难以解释,但数量不是累积的 - 我只需要处理给定用户和给定月份的最新记录,然后我需要对这些数量求和,并按月分组。如果需要更多解释,请说明。
更新:
根据要求,这是一些粗略的psudo代码。这段代码不一定是我所期望的,但它大致是我可以做的,但是以缓慢的,程序化的方式。我希望有一种方法可以通过单个查询来实现这一点,以提高速度。 (顺便说一下,这是基于Manoj Govindan的代码。)
year = list_of_months_that_have_stats
users = all_users_in_database
for months in year:
for user in users:
sum = Stat.object.filter(user=user, entry_date__month=month).order_by('-entry_date')[0].aggregate(sum=Sum('quantity'))
final_output[month] = sum
另外,请注意我正在尝试获取给定月份的最后一条记录。我用order_by做这个,但据我所知这不起作用 - 这只是一个例子。
当然,上面的代码不起作用。拼图的缺失部分是降序order_by,它只获取查询中的第一项。
答案 0 :(得分:1)
我不确定我到底知道你想要什么。如果我没有做对,请参阅下面的答案并纠正我。
我只需要处理 给定用户和给定月份 的最新记录,然后我需要对这些数量求和,并按月分组。
(强调补充)。如果这是您所需要的,那么您可以将filter
与aggregate
结合使用,如下所示。
from django.db.models import Sum
q = Stat.objects.filter(user = user, entry_date__month = 10).aggregate(
sum = Sum('quantity'))
print q
# {'sum': 14}
过滤条件可确保您拥有所需的user
,并且month
的{{1}}部分与您想要的月份匹配(在本例中为10月,因此entry_date
)。然后,您可以10
用户/月份组合的数量。
<强>更新强>
如果你想要每个月的用户总和(我猜这是你的意思,“按月分组”)那么你可以尝试这样的事情:
Sum
这是一个快速解释。
select = dict(month = 'extract(month from entry_date)')
q = Stat.objects.filter(user = user).extra(
select = select).values('month').annotate(
sum = Sum('quantity'))
print q
# [{'sum': 14, 'month': 10.0}, {'sum': 6, 'month': 9.0}]
用于指定您要从日期中提取月份部分。这是特定于数据库的。在我的例子中,语法extra
特定于Postgresql。
使用extract(month from entry_date)
提及您只需要values
。这个很重要。如果省略month
部分,则会获取所有字段,但您将无法获得所需的效果。
最后values
每个记录都带有annotate
。这将返回每个月的总和。