这是我的架构:
城市 - >摄影师
我正在尝试获取至少有一位摄影师的城市名单,并返回城市的摄影师人数。
以下是我正在使用的查询集:
City.objects.annotate(photographer_count=aggregates.Count('photographers')).filter(photographer_count__gt=0).order_by('-photographer_count')
这完全符合我的预期,除了某些原因,Django选择在城市/摄影师与左外连接之间进行连接。如果我抓取SQL文本并简单地将“left outer”更改为“inner”,则查询从~11秒变为200ms,结果相同。
我已经尝试在注释前面添加一个过滤器,向Django暗示它应该是内部连接,但这不起作用。
我可以对此执行任何Django查询voodoo以获得内部联接吗?我意识到我可以使用直接SQL,但更愿意通过ORM。
答案 0 :(得分:6)
默认情况下,会生成LEFT JOIN
,这样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 INNER JOIN
是安全的。 必须来到annotate()
来电之前。
答案 1 :(得分:1)
您通常无法对Django执行的查询和连接进行此级别的控制。
Django并没有做一些非常聪明的事情,比如注意到过滤条件意味着你可以在这一点上使用INNER JOIN - 它必须产生一般情况下正确的查询,在这种情况下意味着LEFT就我所知,外联接。
所以你可能需要原始的SQL。