问题
I have a Person model which has a birthday. I would like to create a query that returns all the persons information along with an additional field that tells how many people are sharing each person's birthday. In SQL I would write it like this:
SELECT p.name, b.count FROM
persons as p INNER JOIN
(SELECT birthday as date, COUNT(*) AS count FROM persons GROUP_BY birthday) AS b
WHERE p.birthday = b.date
With Django querysets I can do the inner select but I don't know how to do the inner join.
回答1:
Seems tough to do with the ORM (though maybe possible with extra).
You could create a dict of counts by date (max 366 values, if ignoring year):
from django.db.models import Count
birthdate = lambda d: d.strftime("%m-%d")
# this runs the subquery in your SQL:
birthdays = Person.objects.values('birthday')
counts = birthdays.annotate(count=Count('birthday'))
counts_by_date = {
birthdate(r['birthday']): r['count']
for r in counts
}
for person in Person.objects.all():
count = counts_by_date[birthdate(person.birthday)]
print "%d people share your birthday!" % count
回答2:
I would add a model method to get the count. You can do it using the ORM like this:
from django.db import models
class Person(models.Model):
birthdate = models.DateField()
def shared_count(self):
return Person.objects.filter(birthdate=self.birthdate).exclude(pk=self.id).count()
Then you can just access the count on the Person instance like this:
my_person = Person.objects.get(pk=12)
count = my_person.shared_count()
Or access it in a template like this:
{{ my_person.shared_count }}
来源:https://stackoverflow.com/questions/31798858/join-two-queries-in-django-orm