Django:如何在distinct()之后过滤()

时间:2014-06-10 20:20:45

标签: django

如果我们在调用distinct()之后将调用链接到filter(),则在distinct之前将过滤器应用于查询。在应用distinct之后如何过滤查询的结果?

Example.objects.order_by('a','foreignkey__b').distinct('a').filter(foreignkey__b='something')

filter()产生的SQL中的where子句表示过滤器在distinct之前应用于查询。我想过滤不同的查询集。

这可能很简单,但我无法弄清楚,我无法找到任何内容。

编辑1:

我需要在ORM中执行此操作...

SELECT z.column1, z.column2, z.column3 FROM ( SELECT DISTINCT ON (b.column1, b.column2) b.column1, b.column2, c.column3 FROM table1 a INNER JOIN table2 b ON ( a.id = b.id ) INNER JOIN table3 c ON ( b.id = c.id) ORDER BY b.column1 ASC, b.column2 ASC, c.column4 DESC ) z WHERE z.column3 = 'Something';

(我顺便使用Postgres。) 所以我想我要问的是"你如何在ORM中嵌套子查询?有可能吗?"我会查看文档。

很抱歉,如果我之前没有具体说明。我头脑中不清楚。

3 个答案:

答案 0 :(得分:5)

这是一个老问题,但在使用Postgres时,您可以执行以下操作来强制对您的“区别”进行嵌套查询。行:

foo = Example.objects.order_by('a','foreign_key__timefield').distinct('a')
bar = Example.objects.filter(pk__in=foo).filter(some_field=condition)

bar是OP中请求的嵌套查询,无需求助于原始/额外等。经测试在1.10中工作但文档建议它应该至少恢复到1.7。

我的用例是过滤反向关系。如果Example有一些ForeignKey来模拟Toast,那么你可以这样做:

Toast.objects.filter(pk__in=bar.values_list('foreign_key',flat=true))

这将为您提供Toast的所有实例,其中最新的关联示例符合您的过滤条件。

关于性能的大健康警告,如果使用这个栏可能是一个巨大的查询集,你可能会有一个糟糕的时间。

答案 1 :(得分:2)

非常感谢帮助人员。我尝试了这两个建议,并且无法将这些建议付诸实践,但我认为它使我开始朝着正确的方向发展。

我最终使用

from django.db.models import Max, F

Example.objects.annotate(latest=Max('foreignkey__timefield')).filter(foreignkey__timefield=F('latest'), foreign__a='Something')

这将检查每个示例的最新foreignkey__timefield是什么,如果它是最新的和a =某事,那么保留它。如果它不是最新的或每个示例的!=那么它就被过滤掉了。

这不会嵌套子查询,但它给了我正在寻找的输出 - 而且它非常简单。如果有更简单的方法我真的想知道。

答案 2 :(得分:1)

不,你不能在一个简单的SELECT中做到这一点 正如您在评论中所说,在Django中,ORM filter映射到SQL子句WHEREdistinct映射到DISTINCT。在SQL中,DISTINCT总是在WHERE之后通过对结果集进行操作,例如,请参阅SQLite doc

但你可以编写子查询来嵌套SELECT,这取决于实际的目标(我不知道你现在究竟是什么......你能详细说明吗?)

另外,对于您的查询,distinct('a')仅保留Example第一次出现的a,这是您想要的吗?