sql >> Database >  >> RDS >> PostgreSQL

Juiste manier om een ​​rangordeveld voor een queryset te annoteren

Helaas is het geen mogelijke operatie sinds (voor mij) de postgresql WHERE bewerking (filteren/uitsluiten) verkleint de rijen voordat de aggregatiefuncties eraan kunnen werken.

De enige oplossing die ik heb gevonden is om eenvoudig de rangorde te berekenen voor alle Person met een aparte queryset en vervolgens, om uw queryset te annoteren met deze resultaten.

Dit antwoord (zie de verbeterde methode) legt uit hoe je "een queryset kunt annoteren met extern voorbereide gegevens in een dictaat".

Dit is de implementatie die ik voor uw modellen heb gemaakt:

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')))

Ik heb het getest met Django 2.1.3 en Postgresql 10.5, dus de code kan voor u licht veranderen.
Geef gerust een versie die compatibel is met Django 1.11!




  1. Oracle sql weekdagen sorteren op huidige dag

  2. Kan ik automatisch een tabel maken in PostgreSQL vanuit een csv-bestand met headers?

  3. Geen reactie op update-query in oracle

  4. Selecteer en retourneer alleen Checksum (geen tabel) uit de checksum-tabel in mysql