2016-11-22 59 views
0

我試圖創建一個模型管理器查詢,該查詢返回按給定日期範圍多個餘額類型(數據和AIRTIME)按天分組的結果。天平歷史表更新爲SIM卡使用數據的所有時間,但報告我們只是想表明一個平衡一天Django查詢將兩行中的值彙總爲單日結果

的模型很簡單:

class Sim(TimeStampedModel): 
    number = models.CharField() 

class SimBalanceHistory(TimeStampedModel): 
    balance_type = models.CharField(choices=BALANCE_TYPES, max_length=10) 
    amount = models.DecimalField(max_digits=10, decimal_places=2, default=0) 
    sim = models.ForeignKey(Sim, related_name='balance_histories') 

從SimBalanceHistory表中的一些樣本數據:

ID BALANCE_TYPE AMOUNT SIM_ID CREATED MODFIED 
    1603 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1604 DATA 36.75 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1703 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1704 DATA 36.74 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1803 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1804 DATA 36.73 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1973 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    1974 DATA 36.72 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2059 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2060 DATA 36.72 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2135 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2136 DATA 36.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2229 AIRTIME 3.71 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 +02:00 
    2230 DATA 36.70 348 2016-11-17 11:13:42.498180 +02:00 2016-11-17 11:13:43.543159 
    440026 DATA 34.26 348 2016-11-18 23:34:36.976777 +02:00 2016-11-18 23:34:36.976836 +02:00 
    440885 AIRTIME 3.71 348 2016-11-18 23:57:57.448809 +02:00 2016-11-18 23:57:57.448878 +02:00 
    440889 DATA 34.25 348 2016-11-18 23:57:58.854901 +02:00 2016-11-18 23:57:58.854959 +02:00 
    443590 AIRTIME 3.71 348 2016-11-19 00:35:07.598679 +02:00 2016-11-19 00:35:07.598755 +02:00 

443593 DATA 34.24 348 2016年11月19日00:35:08.991217 +02:00 2016年11月19日00:35:08.991266

目前查詢看起來是這樣的:

def daily_balances(self, start_date, end_date): 
     return self.filter(
     created__range=[start_date, end_date] 
    ).dates(
     'created', 
     'day', 
     order='DESC' 
    ).order_by(
     '-created' 
    ).distinct(
     'created', 'balance_type' 
    ).values(
     'created', 
     'amount', 
     'balance_type' 
    ) 

這一天限制,但返回的行,每balance_type

{'balance_type': 'AIRTIME', 'created': datetime.datetime(2016, 11, 22, 0, 0, tzinfo=<UTC>), 'amount': Decimal('5.00')} 
{'balance_type': 'DATA', 'created': datetime.datetime(2016, 11, 22, 0, 0, tzinfo=<UTC>), 'amount': Decimal('12.00')} 

我試圖去是這樣的查詢集合的結果(1個記錄每個天數和數據金額:

{'created': datetime.datetime(2016, 11, 22, 0, 0, tzinfo=<UTC>), 'data_amount': Decimal('5.00'), 'airtime_amount': Decimal('12.00')} 
{'created': datetime.datetime(2016, 11, 21, 0, 0, tzinfo=<UTC>), 'data_amount': Decimal('6.00'), 'airtime_amount': Decimal('14.00')} 

回答

0

我覺得你現有的查詢已經是相當不錯的,但如果你真的想每天一組一行兩個餘額,您可以使用conditional aggregates

from django.db.models import IntegerField, F, Sum, When 

SimBalanceHistory.objects\ 
       .filter(created__range=[start_date, end_date])\ 
       .dates('created', 'day', order='DESC')\ 
       .values('created')\ 
       .annotate(airtime_amount=Sum(Case(When(balance_type='AIRTIME', then=F('amount')), output_field=DecimalField())), 
          data_amount=Sum(Case(When(balance_type='DATA', then=F('amount')), output_field=DecimalField()))) 
+0

感謝這是史詩 – WPW

1

這裏是我想嘗試的。

首先,量重命名每行中與特異於它的類型名稱:和DATA_AMOUNT airtime_amount。 然後,在完成每個數量的總和時按「創建」對行進行分組。

所以,我認爲你可以做這樣的事情

from django.db.models import F, Sum 

def daily_balances(self, start_date, end_date): 
    airtime_records = SimBalanceHistory.objects.filter(
     created__range=[start_date, end_date],  
     balance_type='AIRTIME' 
    ).annotate(airtime_amount=F('amount')) 

    data_records = SimBalanceHistory.objects.filter(
     created__range=[start_date, end_date], 
     balance_type='DATA' 
    ).annotate(data_amount=F('amount')) 

    return (airtime_records | data_records).dates(
     'created', 
     'day', 
     order='DESC' 
    ).order_by(
     '-created' 
    ).values('created').annotate(
     Sum('data_amount'), 
     Sum('airtime_amount'), 
    ) 

該代碼使得倍數查詢,但我想不出解決辦法做,在只有一個。希望有人會發布更好的答案,但也許這可以幫助你。

參考文獻。

+0

感謝您的幫助,當我試圖合併兩個查詢集時,它不會允許我,因爲前兩個查詢中的數量字段的名稱不同。 – WPW