[英]How to aggregate sum over multiple date ranges in query set?
是否可以在一個QuerySet
多個日期范圍上注釋.sum()
即,基本上組合這些,因此每個對象具有每個日期范圍的總和。
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()
來實現我的目標,但我認為有更多的Pythonic方法可以實現。
如果你想要多行,你可以聯合兩個查詢集,如下所示:
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查詢!
最重要的是,在評估查詢集之前,django不會執行任何SQL(例如迭代, list()
-ed, len()
ed 等 )。 所以我們只是構建SQL,而不是執行看起來像4個查詢!
大多數數據庫(我認為甚至是sqlite)都有一些查詢優化。 也就是說,它會在兩個查詢中看到重復的內容並首先執行該操作(以代碼看起來正在進行的方式)。 因此,我們應該(最接近)以最有效的方式做到這一點。
所以它不應該太耗時,我想提供一些可讀的代碼(?)!
據我所知,似乎你有兩個幾乎完全相同的查詢,只有date__range
不同。 為什么不嘗試使用Q
-objects在日期范圍內使用SQL 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'))
這似乎一行date__range包含在另: 2018-08-27
- > 2018-08-31
,距離2018-01-01
- > 2018-08-31
。 如果這是您關心的兩個日期范圍,那么您需要的只是第二個查詢..?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.