簡體   English   中英

如何在查詢集中的多個日期范圍匯總和?

[英]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-objects簡而言之

Q對象允許您通過二進制&|來應用ANDOR過濾條件 運營商。 (但是你只需要它們用於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM