2013-10-07 2 views
0

다음 세 개의 테이블을 정의했습니다.Django와 함께 직교 좌표 피하기

운영자를 들어
class Operator(models.Model): 
    DisplayName = models.CharField(max_length=64) 

    class Meta: 
     app_label = "Experiment" 
     db_table = "EXPERIMENT_OPERATOR" 

class OperatorSummary(models.Model): 
    Operator = models.ForeignKey(Operator, related_name="TransactionSummary") 
    TransactionCount = models.IntegerField() 
    TransactionValue = models.DecimalField(max_digits=18, decimal_places=2) 
    StartTime = models.DateTimeField(default=timezone.now()) 

    class Meta: 
     app_label = "Experiment" 
     db_table = "EXPERIMENT_OPERATORSUMMARY" 

class OperatorAlerts(models.Model): 
    Operator = models.ForeignKey(Operator, related_name="AlertSummary") 
    AlertScore = models.IntegerField() 
    AlertCount = models.IntegerField() 
    StartTime = models.DateTimeField(default=timezone.now()) 

    class Meta: 
     app_label = "Experiment" 
     db_table = "EXPERIMENT_OPERATORALERTS" 

, 나는 주어진 기간의 AlertScoreTransactionCount를 검색하고 싶습니다. 쿼리는이 같은 모습을 사용하고 있습니다 :

tz = timezone.get_default_timezone()  
vs = Operator.objects.filter(DisplayName="Jimmy", 
          TransactionSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)), 
          AlertSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)))\ 
    .annotate(TotalTransactions=Sum("TransactionSummary__TransactionCount"), 
       TotalAlerts=Sum("AlertSummary__AlertScore"))\ 
    .values("DisplayName", "TransactionSummary__TransactionCount", "AlertSummary__AlertScore") 

이 쿼리는 카티 제품을 수행하고 쿼리와 일치하는 OperatorAlerts 및 OperatorSummary 테이블의 모든 행을 반환합니다. 이것은 반환 것입니다 :

{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10} 
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10} 
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10} 
{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22} 
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22} 
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22} 
{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234} 
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234} 
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234} 
나는이 문제를 해결하고 싶습니다

그래서 나는 다음과 같은 결과를 얻을 :

{'AlertSummary__AlertScore': 607, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 266} 

모든 결과가 AlertScore 및 TransactionCount가 합산되어 하나의 행으로 축소됩니다 .

그럴 수 있습니까? OperatorAlerts와 OperatorSummary에 대한 별도의 쿼리를 작성한 다음, 결과를 얻기 위해 파이썬에서 결과 집합을 반복 처리하여 .aggregate을 호출 할 수 있습니다. 그러나 더 좋은 방법이 있어야합니다.

답변

1

values()annotate() 방법을 적용하는 순서를 반대로 시도하십시오. values()에 언급 된 필드로

vs = Operator.objects.filter(DisplayName="Jimmy", 
          TransactionSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)), 
          AlertSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)))\ 
    .values("DisplayName")\ 
    .annotate(TotalTransactions=Sum("TransactionSummary__TransactionCount"), 
       TotalAlerts=Sum("AlertSummary__AlertScore")) 

이 의지 그룹에게 결과 다음 각 그룹에 대한 주석을 생성합니다 values() 먼저 와야한다. 순서는 매우 중요합니다 - as documented. 당신이 길을 values()annotate() 적용

(즉 values()annotate()) 별도로 각 항목에 대한 주석을 생성합니다.

위의 코드는 결과를 DisplayName으로 그룹화합니다. 다른 필드 (예 : pk)로 그룹화 할 수 있습니다.

또한 실제 코드에서 여러 연산자에 대한 값을 한꺼번에 가져 오는 것이 좋습니다. 한 번에 한 명의 운영자를 쿼리하면 (예와 같이) annotate() 대신 aggregate()을 사용하는 것이 좋습니다.

+0

매우 도움이되는 답변에 감사드립니다. 여러 연산자를 한꺼번에 쿼리하고 싶습니다. 그러나''annotate''는 여전히'TotalTransactions'와'TotalAlerts'를 모든 사용자에 대해 합계가 아닌 각 사용자에 대해 사용하고자 할 때 필요합니다. – CadentOrange

+0

나는 동의한다, 그것이 내가 의미했던 정확하게 것이다. 나는 틀린 문법적 형식을 사용했기 때문에 문장이 약간 혼란 스럽다고 생각합니다. 나는 지금 그것을 바로 잡았다. –

관련 문제