Leider ist dies keine mögliche Operation, da (für mich) das postgresql WHERE
Der Vorgang (Filtern/Ausschließen) grenzt die Zeilen ein, bevor die Aggregationsfunktionen sie bearbeiten können.
Die einzige Lösung, die ich gefunden habe, besteht darin, einfach das Ranking für alle Person
zu berechnen mit einem separaten Abfragesatz und dann, um Ihren Abfragesatz mit diesen Ergebnissen zu kommentieren.
Diese Antwort (siehe die verbesserte Methode) erklärt, wie man "einen Abfragesatz mit extern aufbereiteten Daten in einem Diktat kommentiert".
Hier ist die Implementierung, die ich für Ihre Modelle gemacht habe:
class PersonQuerySet(models.QuerySet):
def total_scores(self):
# compute the global ranking
ranks = (Person.objects
.annotate(total_score=models.Sum('session__gamesession__score'))
.annotate(rank=models.Window(expression=DenseRank(),
order_by=models.F('total_score').decs()))
.values('pk', 'rank'))
# extract and put ranks in a dict
rank_dict = dict((e['pk'], e['rank']) for e in ranks)
# create `WHEN` conditions for mapping filtered Persons to their Rank
whens = [models.When(pk=pk, then=rank) for pk, rank in rank_dict.items()]
# build the query
return (self.annotate(rank=models.Case(*whens, default=0,
output_field=models.IntegerField()))
.annotate(total_score=models.Sum('session__gamesession__score')))
Ich habe es mit Django 2.1.3 und Postgresql 10.5 getestet, daher kann sich der Code für Sie geringfügig ändern.
Fühlen Sie sich frei, eine Version zu teilen, die mit Django 1.11 kompatibel ist!