我有两张桌子:
票务表
id paid_with_tax location
1 5 A
2 6 B
3 7 B
TicketAdjustment Table
id ticket_id value_with_tax
1 1 2
2 1 1
3 1 2
4 1 3
5 2 5
我使用的查询:
Ticket.objects.all().annotate(
paid_amount=Sum(
F('paid_with_tax') +
Coalesce(F('ticketadjustment__value_with_tax'), 0)
)
).values(
'paid_amount', 'location'
).annotate(
Count('id)
)
查询将返回以下内容:
[
{
id__count: 6,
paid_amount__sum: 28,
location: A
},
{
id__count: 2,
paid_amount__sum: 18,
location: B
},
]
但上述内容不正确,因为Ticket表id = 1值与TicketAdjustment Table值重复。
如何在添加之前获取查询以对TicketAdjustment Table值求和。
一些限制: - 理想情况下,调用的顺序保持不变,因为我有一个函数可以返回要进行过滤的查询集
最终结果应该如下:
[
{
id__count: 1,
paid_amount__sum: 13,
location: A
},
{
id__count: 2,
paid_amount__sum: 18,
location: B
},
]
models.py:
class Ticket(models.Model):
paid_with_tax = models.DecimalField(max_digits=6, decimal_places=4)
location = models.ForeignKey(Location)
class TicketAdjustment(models.Model):
value_with_tax = models.DecimalField(max_digits=6, decimal_places=4)
ticket = models.ForeignKey(Ticket)
答案 0 :(得分:-1)
据我所知,即使使用原始SQL查询也无法进行此聚合。因为使用TicketAdjustment加入Ticket的结果如下:
因此,我们不能将与value_with_tax
某个故障单相关的所有paid_with_tax
与按地点分组。
我找不到在一个sql查询中执行此操作的解决方案。但我已经找到了如何在两个查询中执行此操作:
tickets = Ticket.objects.values(
'location',
).annotate(
count=Count('id', distinct=True),
paid_amount=Sum('paid_with_tax')
)
# <QuerySet [
# {'paid_amount': 5, 'count': 1, 'location': 'A'},
# {'paid_amount': 13, 'count': 2, 'location': 'B'}
# ]>
adjustments = TicketAdjustment.objects.annotate(
location=F('ticket__location'))
.values(
'location',
).annotate(
paid_amount=Sum('value_with_tax')
)
# <QuerySet [
# {'paid_amount': 5, 'location': 'B'},
# {'paid_amount': 8, 'location': 'A'}
# ]>
def find_paid_amount_for_list_and_location(l, location):
for item in l:
if item['location'] == location:
return item['paid_amount'] or 0
for obj in tickets:
paid = find_paid_amount_for_list_and_location(adjustments, obj['location'])
obj['paid_amount'] += paid
tickets
# [
# {'location': 'A', 'paid_amount': 13, 'count': 1},
# {'location': 'B', 'paid_amount': 18, 'count': 2}
# ]
但这不是超级高效的解决方案,我认为您应该为位置创建新表并且只有FK到该表?在这种情况下,您将能够在db端的一个查询中执行这些计算。