Reputation: 2842
I have a Donation
model defined as:
Donation
project = models.ForeignKey(Project)
user = models.CharField()
Each user can donate multiple time to any project, so in db I can have the following:
Donation
-------------------
project | user
-------------------
1 | A
2 | A
3 | A
1 | B
2 | B
2 | C
Now, I need to compute the average of distinct project per user, in this case it would be:
A: 3
B: 2
C: 1
=> ( 3 + 2 + 1 ) / 3 = 2
What I have so far is the following:
distinct_pairs = Donation.objects.order_by('project')
.values('user', 'project')
.distinct()
This gives me a list of distincts project
/user
pairs, that I can work with in python.
I would like to know if there is a query-only
way to do this?
My setup:
Upvotes: 5
Views: 2986
Reputation: 1074
You don't need to sum values for average, you can just count distinct values and divide by number of distinct users. Also order_by
is redundant since we need only counts.
distinct_pairs_count = Donation.objects.values('user', 'project').distinct().count()
distinct_users_count = Donation.objects.values('user').distinct().count()
average = distinct_pairs_count / float(distinct_users_count) # in Python 2
average = distinct_pairs_count / distinct_users_count # in Python 3
EDIT: make it one QuerySet
I think you can achieve this by one query but I can't check it right now:
from django.db.models import Count, Avg
average = Donation.objects.values('user', 'project')
.annotate(num_projects=Count('project', distinct=True))
.aggregate(Avg('num_projects'))
See: aggregating annotations in 1.8
Upvotes: 6