是否可以在一个.sum()
的多个日期范围内对QuerySet
进行注释
也就是说,基本上将它们结合起来,所以每个对象都有每个日期范围的总和。
query_set_week = DailyReports.objects.filter(
date__range=('2018-08-27', '2018-08-31')) \
.select_related('profile') \
.values('profile__user_id') \
.annotate(premium=Sum('total_field'),
first_name=F('profile__user__first_name'),
last_name=F('profile__user__last_name') \
.order_by('profile__agent_code')
query_set_year = DailyReports.objects.filter(
date__range=('2018-01-01', '2018-08-31')) \
.select_related('profile') \
.values('profile__user_id') \
.annotate(premium=Sum('total_field'),
first_name=F('profile__user__first_name'),
last_name=F('profile__user__last_name') \
.order_by('profile__agent_code')
两者都可以单独工作,但是很难遍历和显示数据(例如,用户-周总数-年总数),因为有人可能在年过滤器中有结果,但是在周过滤器中没有。
编辑:目前,我可以使用带有大量SQL语句的.raw()
来实现自己的目标,但是我发现还有一种更Python化的方式来实现它。
答案 0 :(得分:1)
据我所知,您似乎有两个几乎完全相同的查询,只是它们之间的区别是date__range
。为什么不尝试使用Q
-objects
OR
您可以尝试以下操作:
query_set_week_and_year = DailyReports.objects \
.filter(
Q(date__range=('2018-08-27', '2018-08-31')) | Q(date__range=('2018-01-01', '2018-08-31')) \
).select_related('profile') \
.values('profile__user_id') \
.annotate(
premium=Sum('total_field'),
first_name=F('profile__user__first_name'),
last_name=F('profile__user__last_name'
).order_by('profile__agent_code')
Q对象使您可以通过二进制AND
和OR
运算符应用&
和|
过滤条件。 (但是OR
操作只需要它们,因为AND
由过滤器函数中的逗号处理)
例如查找所有以“ A”开头的名字或姓氏的用户:
User.objects.filter(Q(firstname__startswith='A') | Q(lastname__startswith='A'))
似乎第一行的日期__范围包含在另一行中:2018-08-27
-> 2018-08-31
在2018-01-01
-> 2018-08-31
之内。如果这是您关心的两个日期范围,那么您只需要第二个查询即可。
答案 1 :(得分:1)
如果您想要多个行,则可以union two querysets像这样:
base_qs = DailyReports.objects \
.select_related('profile') \
.values('profile__user_id') \
.annotate(premium=Sum('total_field'),
first_name=F('profile__user__first_name'),
last_name=F('profile__user__last_name') \
.order_by('profile__agent_code')
query_set_week = base_qs.filter(date__range=('2018-08-27', '2018-08-31'))
query_set_year = base_qs.filter(date__range=('2018-01-01', '2018-08-31'))
query_set_week_and_year = query_set_week.union(query_set_year)
query_set_week_and_year
应该只执行一个SQL查询就给您两行!
最重要的是,在评估查询集之前(例如,在list()
-ed,len()
-ed,and so on上迭代),django不会执行任何SQL。因此,我们只是在构建SQL,而不是执行看起来像4个查询的操作!
大多数数据库(我认为甚至是sqlite)都有一些查询优化。即它将看到在两个查询中重复的事情,并且首先执行(以某种方式显示代码 在执行)。因此,我们应该(最接近)以最有效的方式进行此操作。
所以它不应该太耗时,我认为它提供了一些可读的代码(?)!