在 django orm 中聚合多对多
aggregate on many to many in django orm
我想为顾问建议的本月持续时间总和创建一个报告。
我的模型:
class Adviser(models.AbstractBaseModel):
user = models.OneToOneField('accounts.User', on_delete=models.PROTECT, related_name='adviser')
patients = models.ManyToManyField('patient.Patient', through='adviser.AdviserPatient', related_name='advisers')
class AdviserPatient(models.AbstractBaseModel):
adviser = models.ForeignKey('adviser.Adviser', on_delete=models.PROTECT, related_name='adviser_patient')
patient = models.ForeignKey('patient.Patient', on_delete=models.PROTECT, related_name='adviser_patient')
duration = models.SmallIntegerField()
assign_date = models.DateField(auto_now_add=True)
release_date = models.DateField(null=True, blank=True)
class Patient(models.AbstractBaseModel):
user = models.OneToOneField('accounts.User', on_delete=models.PROTECT, related_name='patient')
我的查询:
ended_advise_this_mouth = Adviser.objects.annotate(
total=Case(When(
adviser_patient__release_date__gte=start_of_month(),
adviser_patient__release_date__lte=end_of_month(),
then=Sum('adviser_patient__duration')), default=Value(0), output_field=IntegerField()))
但是通过这个查询,我得到了这样的重复顾问:
<QuerySet [<Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [2 vahid imanian]>]>
如您所见,顾问 1 重复 6 次,总计不同。
当我使用方法 values('id') 或使用 distinct() 时,结果不受影响。我的数据库是 mysql 并且不能使用 distinct('id')。
我需要一个 querysetfor pass serializer 请帮我解决这个查询和
有什么方法可以为此查询集使用 django-rest-framework 序列化程序吗?
通过使用 Case
When
,对于每个 adviser_patient
行,它将检查它是否在范围内,并使用该单行的 Sum
(因此持续时间本身),或者 0
如果它超出范围。
因此您需要聚合更高的级别:
from django.db.models import IntegerField, Q, Sum, Value
from django.db.models.functions import Coalesce
# since Django-2.0
ended_advise_this_mouth = Adviser.objects.annotate(
total=Coalesce(Sum(
'adviser_patient__duration',
<b>filter=Q(</b>
adviser_patient__release_date__gte=start_of_month(),
adviser_patient__release_date__lte=end_of_month()
<b>)</b>,
output_field=IntegerField()
), Value(0))
)
我想为顾问建议的本月持续时间总和创建一个报告。 我的模型:
class Adviser(models.AbstractBaseModel):
user = models.OneToOneField('accounts.User', on_delete=models.PROTECT, related_name='adviser')
patients = models.ManyToManyField('patient.Patient', through='adviser.AdviserPatient', related_name='advisers')
class AdviserPatient(models.AbstractBaseModel):
adviser = models.ForeignKey('adviser.Adviser', on_delete=models.PROTECT, related_name='adviser_patient')
patient = models.ForeignKey('patient.Patient', on_delete=models.PROTECT, related_name='adviser_patient')
duration = models.SmallIntegerField()
assign_date = models.DateField(auto_now_add=True)
release_date = models.DateField(null=True, blank=True)
class Patient(models.AbstractBaseModel):
user = models.OneToOneField('accounts.User', on_delete=models.PROTECT, related_name='patient')
我的查询:
ended_advise_this_mouth = Adviser.objects.annotate(
total=Case(When(
adviser_patient__release_date__gte=start_of_month(),
adviser_patient__release_date__lte=end_of_month(),
then=Sum('adviser_patient__duration')), default=Value(0), output_field=IntegerField()))
但是通过这个查询,我得到了这样的重复顾问:
<QuerySet [<Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [1 None None]>, <Adviser: [2 vahid imanian]>]>
如您所见,顾问 1 重复 6 次,总计不同。 当我使用方法 values('id') 或使用 distinct() 时,结果不受影响。我的数据库是 mysql 并且不能使用 distinct('id')。 我需要一个 querysetfor pass serializer 请帮我解决这个查询和 有什么方法可以为此查询集使用 django-rest-framework 序列化程序吗?
通过使用 Case
When
,对于每个 adviser_patient
行,它将检查它是否在范围内,并使用该单行的 Sum
(因此持续时间本身),或者 0
如果它超出范围。
因此您需要聚合更高的级别:
from django.db.models import IntegerField, Q, Sum, Value
from django.db.models.functions import Coalesce
# since Django-2.0
ended_advise_this_mouth = Adviser.objects.annotate(
total=Coalesce(Sum(
'adviser_patient__duration',
<b>filter=Q(</b>
adviser_patient__release_date__gte=start_of_month(),
adviser_patient__release_date__lte=end_of_month()
<b>)</b>,
output_field=IntegerField()
), Value(0))
)