我正在编写一个复杂的django数据查询程序,为了加快返回速度,我使用了值()以及filter()和聚合,并且存在一些重复结果的问题。
想象一下这样的models.py:
class Person(models.Model):
name= CharField()
class Question(models.Model):
title = CharField()
date_asked = DateField()
asker = ForeignKey(person)我想要做的是查询django,使用Person查询集和使用values()来获取一个人的名字和他们最近问题的标题。
如果我们有以下示例数据:
Person | Title | Date
----------------------------------------------
Jack | Where can I get water? | 2011-01-04
Jack | How to climb hill? | 2012-02-05
Jill | How to fix head injury? | 2014-03-06我可以这样做,就像这样:
最近问题的民族名单、姓名和日期:
Person.objects.values('name','most_recent')\\
.annotate('most_recent'=Max('question__date_asked'))
Person | most_recent
--------------------
Jack | 2012-02-05
Jill | 2014-03-06人民名单、姓名及其所有问题和标题:
Person.objects.values('name','question__title','question__date_asked')
Person | Title | Date
----------------------------------------------
Jack | Where can I get water? | 2011-01-04
Jack | How to climb hill? | 2012-02-05
Jill | How to fix head injury? | 2014-03-06但当我试着把它们放在一起时:
Person.objects.values('name','question__title','most_recent')\\
.annotate('most_recent'=Max('question__date_asked'))
.filt
Person | Title | most_recent
----------------------------------------------
Jack | Where can I get water? | 2011-01-04
Jack | How to climb hill? | 2012-02-05
Jill | How to fix head injury? | 2014-03-06即使使用F()表达式也不能解决问题:
Person.objects.values('name','question__title','most_recent')\\
.annotate('most_recent'=Max('question__date_asked'))
.filter('question__date_asked'=F('most_recent'))
Person | Title | most_recent
----------------------------------------------
Jack | Where can I get water? | 2011-01-04
Jack | How to climb hill? | 2012-02-05
Jill | How to fix head injury? | 2014-03-06注:在上表中,给出了每个关系的最大日期,而不是每个人的最大日期。
我需要的是:
Person | Title | most_recent
----------------------------------------------
Jack | How to climb hill? | 2012-02-05
Jill | How to fix head injury? | 2014-03-06语句和联接的排序意味着,当使用筛选器、聚合和值时,同时意味着联接发生在SQL the语句之前,语句应该限制返回行。
关于我如何执行这个查询,有什么想法吗?
更新:
相关的SQL查询如下所示:
SELECT "example_person"."full_name", "example_question"."title",
MAX("example_question"."date_asked") AS "max___example_question__date_asked"
FROM "example_person"
LEFT OUTER JOIN
"example_question" ON ( "example_person"."id" = "example_question"."person_id" )
INNER JOIN
"example_question" T3 ON ( "example_person"."id" = T3."person_id" )
GROUP BY
"example_person"."full_name", T3."start_date",
"example_person"."id", "example_question"."title"
HAVING
T3."date_asked" = (MAX("example_person"."date_asked"))这个问题与djangos与GROUP BY语句的特异性有关。如果我运行./manage.py dbshell并运行上面的查询,就会得到冗余的结果,但是如果我将其限制为GROUP BY "example_person"."full_name"而没有其他分组,我就会得到正确的结果。
有没有办法限制django的GROUP BY或者某种猴子补丁来限制它呢?
发布于 2015-07-27 15:52:06
根据后端的不同,您应该能够使用这样的order_by和distinct来完成这一任务:
Question.objects.order_by('asker__name', '-date').distinct('asker__name')这应该按照被问者的姓名和日期进行排序,然后为每个被问者接受第一个问题,这将是最新的问题。您没有提到您正在使用的后端,所以如果您使用的是像SQLite这样的不支持不同的东西,那么您可能不得不用另一种方法。
发布于 2015-07-27 23:26:02
这是一个部分的答案,我会更新,但我找到了一个方法。
Django不喜欢你玩GROUP BY语句,它们被埋得很深。太深了。
但是,使用这个(只使用Django 1.7 )的猴子补丁,您可以覆盖分组是如何完成的。在下面的示例中,我们捕获了django认为您应该拥有的分组,然后将其剪回当且仅当该查询使用聚合(只有在存在聚合时才填充having_group_by参数。
_get_grouping = SQLCompiler.get_grouping
def custom_get_grouping(compiler,having_group_by, ordering_group_by):
fields,thing = _get_grouping(compiler,having_group_by, ordering_group_by)
if having_group_by:
fields = fields[0:1]+[".".join(f) for f in having_group_by]
return fields,thing
SQLCompiler.get_grouping = custom_get_grouping希望很快会有更好的办法..。
https://stackoverflow.com/questions/31643558
复制相似问题