我有三种型号如下:
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
class PersonSession(models.Model):
start_time = models.DateTimeField(auto_now_add=True)
end_time = models.DateTimeField(null=True,
blank=True)
person = models.ForeignKey(Person, related_name='sessions')
class GameSession(models.Model):
score = models.PositiveIntegerFeild()
person_session = models.ForeignKey(PersonSession, related_name='games')
现在我想获得计算所有分数的人员名单加上他们在所有游戏会话和分支会话中花费的时间,我目前使用的查询如下:
Person.objects.annotate(game_score=Sum(Case(When(Q(sessions__games__isnull=True),
then=0),
default=F('sessions__games__score'),
output=models.PositiveIntegerField())))\
.annotate(spent_time=Sum(Case(When(Q(branch_sessions__isnull=False) &
Q(branch_sessions__end_time__isnull=False),
then=ExpressionWrapper(ExtractHour(ExpressionWrapper(F('sessions__end_time')-F('sessions__start_time'),
output_field=models.TimeField()),
output=models.PositiveIntegerField()) * 60 + \
ExtractMinute(ExpressionWrapper(F('sessions__end_time')-F('sessions__start_time'),
output_field=models.TimeField()),
output=models.PositiveIntegerField()),
output_field=models.PositiveIntegerField())),
default=0,
output=models.PositiveIntegerField()))) \
.annotate(total_score=F('game_score') + F('spent_time') * SCORE_MIN)\
.order_by('-total_score')
问题在于此查询将所有表连接在一起,因此对于每个PersonSession
,我们可能有许多GameSession
,结果表包含人员会话的重复行,这会导致人员会话的时间反复总结并产生错误的结果。
在sql查询中,我必须首先构建一个带有游戏社交总和的子表,然后将该表与人员会话连接起来,但我不知道这怎么可能在django中?
我正在使用django 1.11和postgres。