我有这些模特:
User:
email = EmailField()
Payment:
user = ForeignKey(User)
sum = DecimalField()
GuestAccount:
user = ForeignKey(User)
guest = ForeignKey(User)
我想收到用户的电子邮件,来自每个用户的金额 和客人帐号。
我的查询:
User.objects.annotate(
money=Sum('payment__sum'),
guests_number=Count('guestaccount')
).values('email', 'money', 'guests_number')
但是查询结果中的money
和guests_number
大于实际值:
{'guests_number': 0, 'email': 'a@b.cd', 'money': None}
{'guests_number': 20, 'email': 'user1@mail.com', 'money': Decimal('6600.00')}
{'guests_number': 4, 'email': 'user1000@test.com', 'money': Decimal('2500.00')}
{'guests_number': 0, 'email': 'zzzz@bbbbb.com', 'money': None}
如果我将查询分成两个单独的查询,我注意到我得到了正确的数据:
User.objects.annotate(money=Sum('payment__sum')).values('email', 'money')
User.objects.annotate(guests_number=Count('guestaccount')).values('email', 'guests_number')
上半场的正确结果:
{'email': 'a@b.cd', 'money': None}
{'email': 'user1@mail.com', 'money': Decimal('1650.00')}
{'email': 'user1000@test.com', 'money': Decimal('1250.00')}
{'email': 'zzzz@bbbbb.com', 'money': None}
下半场的正确结果:
{'email': 'a@b.cd', 'guests_number': 0}
{'email': 'user1@mail.com', 'guests_number': 4}
{'email': 'user1000@test.com', 'guests_number': 2}
{'email': 'zzzz@bbbbb.com', 'guests_number': 0}
另外,我注意到我可以在distinct=True
聚合中添加Count
:
User.objects.annotate(
money=Sum('payment__sum'),
guests_number=Count('guestaccount', distinct=True)
).values('email', 'money', 'guests_number')
它修复了guests_number
:
{'guests_number': 0, 'email': 'a@b.cd', 'money': None}
{'guests_number': 4, 'email': 'user1@mail.com', 'money': Decimal('6600.00')}
{'guests_number': 2, 'email': 'user1000@test.com', 'money': Decimal('2500.00')}
{'guests_number': 0, 'email': 'zzzz@bbbbb.com', 'money': None}
不幸的是,distinct
聚合中没有Sum
参数。
我的查询有什么问题?如何通过注释中的每个聚合来修复这些数字变大?
答案 0 :(得分:0)
原始SQL查询调查显示问题来自多个LEFT OUTER JOIN。所以我最终得到了原始的SQL:
User.objects.extra(select={
"money": """
SELECT SUM("website_payment"."sum")
FROM "website_payment"
WHERE "website_user"."id" = "website_payment"."user_id"
""",
"guests_number": """
SELECT COUNT("guests_guestaccount"."id")
FROM "guests_guestaccount"
WHERE "website_user"."id" = "guests_guestaccount"."user_id"
""",
}
).values('email', 'money', 'guests_number')
但我需要将这些字段注释为查询对象,extra
不要这样做。