PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Richtiger Weg, um ein Rangfeld für einen Abfragesatz zu kommentieren

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!