Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group by AND aggregate with Django

I have a fairly simple query I'd like to make via the ORM, but can't figure that out..

I have three models:

Location (a place), Attribute (an attribute a place might have), and Rating (a M2M 'through' model that also contains a score field)

I want to pick some important attributes and be able to rank my locations by those attributes - i.e. higher total score over all selected attributes = better.

I can use the following SQL to get what I want:

select location_id, sum(score)      from locations_rating      where attribute_id in (1,2,3)      group by location_id order by sum desc; 

which returns

 location_id | sum  -------------+-----           21 |  12            3 |  11 

The closest I can get with the ORM is:

Rating.objects.filter(     attribute__in=attributes).annotate(     acount=Count('location')).aggregate(Sum('score')) 

Which returns

{'score__sum': 23} 

i.e. the sum of all, not grouped by location.

Any way around this? I could execute the SQL manually, but would rather go via the ORM to keep things consistent.

Thanks

like image 517
Guy Bowden Avatar asked Nov 15 '12 18:11

Guy Bowden


People also ask

What is Groupby in Django?

The GROUP BY statement is used to combine rows with the same values, and it is mostly used with aggrege functions like COUNT(), AVG(), SUM(), etc. Whereas, the Django ORM is an abstraction layer that allows us to work with the database by translating the python code into a SQL statement.

What does aggregate do in Django?

When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.

How can I filter a Django query with a list of values?

To filter a Python Django query with a list of values, we can use the filter method with in . to search Blog entries with pk set to 1,4 or 7 by calling Blog. objects. filter with the pk_in argument set to [1, 4, 7] .

What is the difference between aggregate and annotate in Django?

Aggregate calculates values for the entire queryset. Annotate calculates summary values for each item in the queryset.


1 Answers

Try this:

Rating.objects.filter(attribute__in=attributes) \     .values('location') \     .annotate(score = Sum('score')) \     .order_by('-score') 
like image 83
Aamir Rind Avatar answered Oct 10 '22 01:10

Aamir Rind