这些是我的django模型(简化):
class Status(models.Model):
status = models.CharField(max_length=20)
class Project(models.Model):
client = models.ForiegnKey(Client)
class TicketRequest(models.Model):
status = models.ForiegnKey(Status, related_name='ticket_requests')
project = models.ForiegnKey(Project)
created = models.DateTimeField()
status.value | client.id | count
--------------+-------------+---------
is_assigned | 4 | 2
is_closed | 4 | 66
is_open | 4 | 7
Status.objects.filter(
ticket_requests__project__client_id=4
).values('value').annotate(
count=Count('ticket_requests__project__client')
)
返回
[{'count': 2, 'value': u'is_assigned'}, {'count': 66, 'value': u'is_closed'}, {'count': 7, 'value': u'is_open'}]
这正是所需要的。
但我需要使用过滤器(如今天,本周和月份)过滤TicketRequest.created
上的查询集。
由于这些过滤器需要重复使用,我创建了一个方便的帮助器:
def qs_time_range(qs, time_range, field_name):
now = timezone.now()
if time_range == 'month':
past = now - timedelta(days=30)
return qs.filter(
**{field_name + '__date__range': [past, now]}
)
当我使用帮助程序过滤故障单请求时,结果不是我所期望的。
data = filters.qs_time_range(
Status.objects.filter(ticket_requests__project__client_id=4),
'month',
'ticket_requests__created'
).values('value').annotate(
count=Count('ticket_requests__project__client')
)
结果
[{'count': 27, 'value': u'is_assigned'}]
相反,这应该是结果:
[{'count': 3, 'value': u'is_assigned'}, {'count': 3, 'value': u'is_closed'}, {'count': 3, 'value': u'is_open'}]
问题:过滤是否会破坏SQL?我该怎么办呢?
data.query
显示此SQL(为Postgres修改)
SELECT "tickets_status"."value",
COUNT("projects_project"."client_id") AS "count"
FROM "tickets_status"
INNER JOIN "tickets_ticketrequest" ON ("tickets_status"."id" = "tickets_ticketrequest"."status_id")
INNER JOIN "projects_project" ON ("tickets_ticketrequest"."project_id" = "projects_project"."id")
INNER JOIN "tickets_ticketrequest" T5 ON ("tickets_status"."id" = T5."status_id")
WHERE ("projects_project"."client_id" = 4
AND T5."created"::date BETWEEN '2016-09-02' AND '2016-10-02')
GROUP BY "tickets_status"."value",
"tickets_status"."name"
ORDER BY "tickets_status"."name" ASC;
返回
value | count
-------------+-------
is_assigned | 27
(1 row)
但这是我想要生成的SQL:
SELECT "tickets_status"."value",
COUNT("projects_project"."client_id") AS "count"
FROM "tickets_status"
INNER JOIN "tickets_ticketrequest" ON ("tickets_status"."id" = "tickets_ticketrequest"."status_id")
INNER JOIN "projects_project" ON ("tickets_ticketrequest"."project_id" = "projects_project"."id")
WHERE ("projects_project"."client_id" = 4
AND "tickets_ticketrequest"."created"::date BETWEEN '2016-09-02' AND '2016-10-02')
GROUP BY "tickets_status"."value",
"tickets_status"."name"
ORDER BY "tickets_status"."name" ASC;
返回正确结果
value | count
-------------+-------
is_assigned | 3
(3 rows)
答案 0 :(得分:1)
很高兴听到你让你的东西工作,但这个答案只是一个解释,而不是这个魔法背后的推理。我记得这很有效,但如果有人想出一个解释为什么它有效,那么这才是真正正确的答案。但是,如果django.db.models.Count
无法按预期工作,您可以将其替换为Sum(Case(When(field='value'), then=1), default=0, output_field=models.IntegerField())
(在Django> = 1.9中)的组合。
解决问题的原始评论:
首先必须说清楚:你确定你有吗? 上个月创建的已关闭或打开的机票请求?那会 是最明显的原因。但如果你已经加倍了 三重检查,然后我有一个类似的模糊记忆 问题在哪里,但不记得为什么。但我通过改变来修复它 Count()到Sum(Case(当(set__the__condition ='set_the_value')时, then = 1),default = 0,output_field = models.IntegerField()))。