Django 中 QuerySet 中特定列的平均重复项
Average duplicates from specific columns in QuerySet in Django
我有一个正在使用的 Django 模型,它看起来像这样:
class FinancialAid(models.Model):
RECEIVED_EVERY = (("J", "Jours"),
("S", "Semaines"),
("M", "Mois"))
ID = models.AutoField(primary_key=True)
Name = models.CharField(max_length=100, null=True, blank=True)
Value = models.IntegerField(null=True, blank=True, default=-1)
ReceivedEvery = models.CharField(max_length=15, null=True, blank=True, choices=RECEIVED_EVERY)
Exchange = models.ForeignKey('Exchange', on_delete=models.CASCADE)
我能够访问我想要的信息,但我有一个问题,我的 QuerySet 中经常在 Name
和 ReceivedEvery
列上有重复项,但并不总是在 Value
并且永远不会出现在 Exchange
.
假设我扩展了以下 QuerySet:
financial_aid_qs = [
(ID=1, Name="Aid1", Value=100, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=1)),
(ID=2, Name="Aid2", Value=200, ReceivedEvery="S", Exchange=Exchange.objects.get(pk=2)),
(ID=3, Name="Aid1", Value=150, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=3)),
(ID=4, Name="Aid3", Value=100, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=4))
]
如您所见,我对索引 1 和 3 有相同的 Name
和 ReceivedEvery
。我想做的是获取一个 QuerySet(或 ValuesQuerySet,尽管我似乎记得这个已删除),它将包含 Name
方面的所有不同 FinancialAid 对象,并对具有相同 Name
的 FinancialAid 对象的 Value
进行平均。理想情况下,它会考虑到 ReceivedEvery
可以不同的事实,即使 Name
是相同的(这都是平均值,所以不需要完美,这就是为什么为了这个,一个月是 30 天或 4 周)。
有了这一切,结果应该是这样的:
financial_aid_qs = [
(Name="Aid1", Value=125, ReceivedEvery="M"),
(Name="Aid2", Value=200, ReceivedEvery="S"),
(Name="Aid3", Value=100, ReceivedEvery="M")
]
如您所见,对于Aid1
,该值已从 100 和 150 平均为 125,其他 Aids 未修改。
使用values()
聚合分组查询,例如:
financial_aid_qs = FinancialAid.objects.values("Name").annotate(avg_value=Avg("Value"))
这将 return 字典的查询集(当执行列表时):
financial_aid_qs = [
{'Name': "Aid1", 'avg_value': 125},
{'Name': "Aid2", 'avg_value': 200},
...
]
如果您还想通过 ReceivedEvery
进行区分,那么您只需按两个值进行分组:
financial_aid_qs = FinancialAid.objects.values('Name', 'ReceivedEvery').annotate(...)
>>> [{'Name': "Aid1", 'ReceivedEvery': "M", 'avg_value': 125},
{'Name': "Aid1", 'ReceivedEvery': "S", 'avg_value': 200}, ...]
在这里,每周和每月的捐款将被分开"Name"。
使用 conditional expression 根据其他值创建新值:
financial_aid_qs = FinancialAid.objects.annotate(
factor=Case(
When(ReceivedEvery="S", then=Value(4)),
When(ReceivedEvery="M", then=Value(1)),
output_field=IntegerField()
)).annotate(
total=F('factor')*F('Value')
).values('Name').annotate(
avg_value=Avg('total')
)
我有一个正在使用的 Django 模型,它看起来像这样:
class FinancialAid(models.Model):
RECEIVED_EVERY = (("J", "Jours"),
("S", "Semaines"),
("M", "Mois"))
ID = models.AutoField(primary_key=True)
Name = models.CharField(max_length=100, null=True, blank=True)
Value = models.IntegerField(null=True, blank=True, default=-1)
ReceivedEvery = models.CharField(max_length=15, null=True, blank=True, choices=RECEIVED_EVERY)
Exchange = models.ForeignKey('Exchange', on_delete=models.CASCADE)
我能够访问我想要的信息,但我有一个问题,我的 QuerySet 中经常在 Name
和 ReceivedEvery
列上有重复项,但并不总是在 Value
并且永远不会出现在 Exchange
.
假设我扩展了以下 QuerySet:
financial_aid_qs = [
(ID=1, Name="Aid1", Value=100, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=1)),
(ID=2, Name="Aid2", Value=200, ReceivedEvery="S", Exchange=Exchange.objects.get(pk=2)),
(ID=3, Name="Aid1", Value=150, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=3)),
(ID=4, Name="Aid3", Value=100, ReceivedEvery="M", Exchange=Exchange.objects.get(pk=4))
]
如您所见,我对索引 1 和 3 有相同的 Name
和 ReceivedEvery
。我想做的是获取一个 QuerySet(或 ValuesQuerySet,尽管我似乎记得这个已删除),它将包含 Name
方面的所有不同 FinancialAid 对象,并对具有相同 Name
的 FinancialAid 对象的 Value
进行平均。理想情况下,它会考虑到 ReceivedEvery
可以不同的事实,即使 Name
是相同的(这都是平均值,所以不需要完美,这就是为什么为了这个,一个月是 30 天或 4 周)。
有了这一切,结果应该是这样的:
financial_aid_qs = [
(Name="Aid1", Value=125, ReceivedEvery="M"),
(Name="Aid2", Value=200, ReceivedEvery="S"),
(Name="Aid3", Value=100, ReceivedEvery="M")
]
如您所见,对于Aid1
,该值已从 100 和 150 平均为 125,其他 Aids 未修改。
使用values()
聚合分组查询,例如:
financial_aid_qs = FinancialAid.objects.values("Name").annotate(avg_value=Avg("Value"))
这将 return 字典的查询集(当执行列表时):
financial_aid_qs = [
{'Name': "Aid1", 'avg_value': 125},
{'Name': "Aid2", 'avg_value': 200},
...
]
如果您还想通过 ReceivedEvery
进行区分,那么您只需按两个值进行分组:
financial_aid_qs = FinancialAid.objects.values('Name', 'ReceivedEvery').annotate(...)
>>> [{'Name': "Aid1", 'ReceivedEvery': "M", 'avg_value': 125},
{'Name': "Aid1", 'ReceivedEvery': "S", 'avg_value': 200}, ...]
在这里,每周和每月的捐款将被分开"Name"。
使用 conditional expression 根据其他值创建新值:
financial_aid_qs = FinancialAid.objects.annotate(
factor=Case(
When(ReceivedEvery="S", then=Value(4)),
When(ReceivedEvery="M", then=Value(1)),
output_field=IntegerField()
)).annotate(
total=F('factor')*F('Value')
).values('Name').annotate(
avg_value=Avg('total')
)