简体   繁体   中英

Django query, average count distinct

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:

  • Django 1.8
  • PostgreSQL

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

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