简体   繁体   中英

Using a subquery in Django and annotate the results with the average value - remove GROUP BY

I'm using Django 3 and am trying to get a subquery going to retrieve the average value from a different table. Here is my setup:

class People(models.Model):
    name = models.CharField(max_length=255)

class Rating(models.Model):
    people = models.ForeignKey(People, on_delete=models.CASCADE)
    rating = models.PositiveSmallIntegerField() # rating from 1-10
    rated_by = models.ForeignKey(User, on_delete=models.CASCADE)

So you can get multiple users to give a rating to individual people. What I would like to get is therefore the average rating for each record in the People table. Something like:

people_id | people_name | avg_rating
-------------------------------------
1         | maria       | 7.2
2         | john        | 5.3
3         | marta       | 7.3
4         | felipe      | 4.1

In SQL, this would be something like:

SELECT people.*, (SELECT avg(rating) FROM rating WHERE people_id=people.id) AS avg_rating FROM people

This is how I tried in Django:

rating = Rating.objects.filter(people=OuterRef("people")).values("rating")
avg_ratings = ratings.annotate(avg_rating=Avg("rating")).values("avg_rating")
people = People.objects.all().annotate(average_rating=Subquery(avg_ratings))

But it returns this error:

more than one row returned by a subquery used as an expression

When I analyze the SQL code, this is what it generates:

SELECT people.*, (SELECT avg(rating) FROM rating WHERE people_id=people.id GROUP BY rating) AS avg_rating FROM people

So basically the GROUP BY rating part is what needs to be removed... without that, this would work perfectly. But how can I do this?

This worked for me

rating = Rating.objects.filter(people=OuterRef("id")).values("people")
avg_ratings = rating.annotate(avg_rating=Avg('rating')).values("avg_rating")
people = People.objects.all().annotate(average_rating=Subquery(avg_ratings))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM