5

这是我的架构:

城市 --> 摄影师

我正在尝试获取至少有一名摄影师的城市列表,并返回城市的摄影师人数。

这是我正在使用的查询集:

City.objects.annotate(photographer_count=aggregates.Count('photographers')).filter(photographer_count__gt=0).order_by('-photographer_count')

这也完全符合我的预期,除了出于某种原因 Django 选择使用左外连接在城市/摄影师之间进行连接。如果我抓取 SQL 文本并简单地将“左外”更改为“内”,则查询从约 11 秒变为 200 毫秒,结果相同。

我尝试在注释前面放置一个过滤器,以向 Django 提示它应该是内部连接,但这没有用。

我可以对此执行任何 Django 查询伏都教以获得内部连接?我意识到我可以直接使用 SQL,但更愿意通过 ORM。

4

2 回答 2

15

默认情况下,LEFT JOIN生成 a 以便 Django 可以为您提供行,即使对于摄影师为零的城市也是如此。如果你知道你不想要这些,这里有一个强制 Django 生成的技巧INNER JOIN

City.objects.filter(
    photographer__isnull=False
).annotate(
    photographer_count=aggregates.Count('photographers')
).filter(
    photographer_count__gt=0
).order_by(
    '-photographer_count'
)

具体来说,第一个过滤器告诉 Django anINNER JOIN是安全的。它必须annotate()调用之前出现。

于 2017-08-08T01:21:17.310 回答
0

您通常无法对 Django 执行的查询和连接进行这种级别的控制。

Django 并没有做真正聪明的事情,比如注意到过滤条件意味着你可以在这一点上摆脱 INNER JOIN - 它必须产生在一般情况下正确的查询,在这种情况下意味着 LEFT OUTER JOIN 为据我所知。

因此,您可能需要原始 SQL。

于 2012-07-23T23:52:56.247 回答