You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django ORM中实现多左连接并统计关联表记录数

Django ORM实现Companies表与子表左连接并统计关联次数

嘿,我来帮你把这条原生PostgreSQL查询转换成Django ORM的写法,完美匹配你的需求~

首先,咱们先对齐思路:原生SQL里是先对两张子表做分组计数,再左连接到Companies表,保留所有公司记录,没有关联记录的计数返回null。用Django ORM的话,我们可以用Subquery和OuterRef来复刻这个子查询逻辑,避免多表连接带来的计数误差。

具体实现代码

首先导入需要的模块:

from django.db.models import Count, Subquery, OuterRef
from django.db import models

然后构建两个子查询,分别计算每个公司在两张子表中的出现次数:

# 构建OrPodanieIssues的计数子查询
or_podanie_count_subquery = OrPodanieIssues.objects.filter(
    company_id=OuterRef('cin')  # 关联Companies的cin字段
).values('company_id').annotate(
    count=Count('id')  # 统计当前company_id的记录数
).values('count')  # 只提取计数值

# 构建ZnizenieImaniaIssues的计数子查询
znizenie_count_subquery = ZnizenieImaniaIssues.objects.filter(
    company_id=OuterRef('cin')
).values('company_id').annotate(
    count=Count('id')
).values('count')

最后查询Companies表,同时把两个计数字段添加到结果中:

companies_with_counts = Companies.objects.annotate(
    # 把子查询的结果作为新字段添加,指定输出类型为IntegerField
    or_podanie_issues_count=Subquery(or_podanie_count_subquery, output_field=models.IntegerField()),
    znizenie_imania_issues_count=Subquery(znizenie_count_subquery, output_field=models.IntegerField())
).values(
    # 指定需要返回的字段,和原生SQL输出一致
    'cin', 'name', 'br_section', 'adress_line', 'last_update',
    'or_podanie_issues_count', 'znizenie_imania_issues_count'
)

效果说明

  • 这段ORM代码生成的SQL和你提供的原生查询几乎一致,保证执行效率和结果准确性
  • 如果某个公司在子表中没有关联记录,对应的计数字段会返回None,和你示例中的null效果完全匹配
  • 遍历companies_with_counts就能得到你想要的结果格式,比如:
for company in companies_with_counts:
    print(company)

输出示例:

{
    'cin': 9110007690010,
    'name': "Alžbeta Škrováňová",
    'br_section': None,
    'adress_line': "Za Humnami, 95161 Čifáre",
    'last_update': datetime.datetime(2018, 9, 19, 3, 0, 32, 851000),
    'or_podanie_issues_count': 3,
    'znizenie_imania_issues_count': None
}

为什么不用直接annotate Count?

如果直接用Companies.objects.annotate(or_count=Count('orpodanieissues'))的方式,当一个公司同时有多个OrPodanieIssues和ZnizenieImaniaIssues记录时,会因为多表连接产生笛卡尔积,导致计数结果不准确。而用子查询的方式完全复刻了原生SQL的逻辑,能避免这个问题。

内容的提问来源于stack exchange,提问作者Chiller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:24:04