Django - 过滤查询集直到达到总和
Django - filter queryset until Sum is reached
让我们想象一个名为 Roll
的模型。它存储掷六面骰 (D6) 的结果:
class Roll(models.Model):
outcome = models.PositiveSmallIntegerField('Roll', null=False, blank=False, default=1)
有很多卷,例如:
print(list(Roll.objects.all().values_list('outcome', flat=True)))
>>> [1, 5, 6, 3, 5, 4, 4, 3, 2]
现在,我应该如何获取 Sum('outcome') 达到任意数量的最新 N 行,而不以某种方式循环,直到达到该数量?
如果我们想象一下面包卷:
pk | outcome | (accumulated sum)
1 | 3 | 3
2 | 2 | 5
3 | 6 | 11
4 | 1 | 12
5 | 5 | 17
6 | 4 | 21
7 | 3 | 24
8 | 4 | 29
9 | 5 | 34
10 | 1 | 35
和任意数量 20
,然后查询应选择 pk 6
,因为累计总和现已达到所需数量。
类似下面的东西可以工作吗?:
amount = 100
Roll.objects.annotate(
accumulated_sum=Subquery(
Roll.objects.filter(
pk__lte=OuterRef('pk')
).values('pk').order_by('pk').annotate(
sum=Sum('outcome', distinct=True)
).values(
'sum'
)[:1]
)
).filter(
accumulated_sum__gte=amount
)
这可能有助于注释 accumuated_sum:
from django.db.models import Subquery, IntegerField
class SQSum(Subquery):
output_field = IntegerField()
template = "(SELECT sum(outcome) from (%(subquery)s) _sum)"
accumulated_subquery = SQSum(
Roll.objects.filter(
pk__lte=OuterRef('pk')
).values("outcome")
)
Roll.objects.annotate(accumulated_sum=accumulated_subquery).filter(accumulated_sum__gte=amount)
让我们想象一个名为 Roll
的模型。它存储掷六面骰 (D6) 的结果:
class Roll(models.Model):
outcome = models.PositiveSmallIntegerField('Roll', null=False, blank=False, default=1)
有很多卷,例如:
print(list(Roll.objects.all().values_list('outcome', flat=True)))
>>> [1, 5, 6, 3, 5, 4, 4, 3, 2]
现在,我应该如何获取 Sum('outcome') 达到任意数量的最新 N 行,而不以某种方式循环,直到达到该数量?
如果我们想象一下面包卷:
pk | outcome | (accumulated sum)
1 | 3 | 3
2 | 2 | 5
3 | 6 | 11
4 | 1 | 12
5 | 5 | 17
6 | 4 | 21
7 | 3 | 24
8 | 4 | 29
9 | 5 | 34
10 | 1 | 35
和任意数量 20
,然后查询应选择 pk 6
,因为累计总和现已达到所需数量。
类似下面的东西可以工作吗?:
amount = 100
Roll.objects.annotate(
accumulated_sum=Subquery(
Roll.objects.filter(
pk__lte=OuterRef('pk')
).values('pk').order_by('pk').annotate(
sum=Sum('outcome', distinct=True)
).values(
'sum'
)[:1]
)
).filter(
accumulated_sum__gte=amount
)
这可能有助于注释 accumuated_sum:
from django.db.models import Subquery, IntegerField
class SQSum(Subquery):
output_field = IntegerField()
template = "(SELECT sum(outcome) from (%(subquery)s) _sum)"
accumulated_subquery = SQSum(
Roll.objects.filter(
pk__lte=OuterRef('pk')
).values("outcome")
)
Roll.objects.annotate(accumulated_sum=accumulated_subquery).filter(accumulated_sum__gte=amount)