首页 > 解决方案 > Django如何找到反向FK的总和和反向FK的反向FK

问题描述

由于绝对出色的数据库设计,我偶然发现了一个问题。我正在计算反向 FK 匹配和 ITS 反向 FK 匹配的数量(按照这个 SO 问题中的方法:Django QuerySet ordering by number of reverse ForeignKey matches)。我试着做:

assert 6 == Model.objects.annotate(counting=Count(f"blah1") + Count(f"blah1__blah2")).get(id=1).counting

但我得到6 == 7的查询总是给我一个额外的 1。这是为什么呢?

编辑:模型:

class Model(models.Model):
    ...

class Blah1(models.Model):
    parent = models.ForeignKey(Model, on_delete=models.CASCADE)

class Blah2(models.Model):
    parent = models.ForeignKey(Blah1, on_delete=models.CASCADE)

标签: pythondjangodjango-models

解决方案


Count('blah1')将计算与 相同数量的项目Count('blah1__blah2'),因为您进行了 JOIN。事实上,查询看起来像:

SELECT model.*, COUNT(blah1.id) + COUNT(blah2.id) AS counting
FROM model
LEFT OUTER JOIN blah1.parent = model.id
LEFT OUTER JOIN blah2.parent = blah1.id

COUNT不关心值,或者值是重复的,它只会不计算sNULL,但对于其余的,COUNT(blah1.id)可能COUNT(blah2.id)几乎相同。

因此,您应该计算的唯一blah1

from django.db.models import Count

Model.objects.annotate(
    counting=Count('blah1', distinct=True) +
             Count('blah1__blah2')
).get(id=1).counting

因此,在这里我们将只计算不同的blah1对象。


推荐阅读