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

Django ORM实现Parent与多子表、关联表的Inner Join多表连接查询

Django ORM多表内连接查询实现方案

你给出的SQL是以Parent表为主表,内联所有子表及关联的OtherTable,要求返回同时存在Child1、Child2、Child3关联记录的Parent数据,Django ORM可通过以下方式实现等效查询:


核心实现代码

因为Parent到三个Child表是反向外键关联,默认反向关联名为child1_set、child2_set、child3_set(未自定义related_name的前提下),通过filter触发反向关联的内连接,配合select_related处理Child3到OtherTable的正向关联即可:

# 如需平铺返回所有关联表字段,等效于SQL的select *
from django.db.models import F

queryset = Parent.objects.filter(
    # 触发三个子表的内连接,仅保留同时有三类子表关联的Parent记录
    child1__isnull=False,
    child2__isnull=False,
    child3__isnull=False
# 预加载Child3关联的OtherTable,走内连接
).select_related(
    "child3__other_table"
# 指定返回所有需要的字段,双下划线表示跨表取字段
).values(
    # Parent表字段示例,替换为实际字段名
    "id", "parent_field1", "parent_field2",
    # Child1表字段
    "child1__id", "child1__field1",
    # Child2表字段
    "child2__id", "child2__field1",
    # Child3表字段
    "child3__id", "child3__field1",
    # OtherTable表字段
    "child3__other_table__id", "child3__other_table__field1"
)

# 打印生成的SQL和参数验证
print(queryset.query.sql_with_params())

其他使用场景

如果你需要返回对象实例而非平铺字段,可改用prefetch_related预加载所有关联对象,避免N+1查询:

queryset = Parent.objects.filter(
    child1__isnull=False,
    child2__isnull=False,
    child3__isnull=False
).prefetch_related(
    "child1_set", "child2_set", "child3_set", "child3__other_table"
)

# 遍历访问关联对象不会触发额外查询
for parent in queryset:
    child1_items = parent.child1_set.all()
    child2_items = parent.child2_set.all()
    child3_items = parent.child3_set.all()
    for child3 in child3_items:
        other_item = child3.other_table

注意事项

  • 如果外键字段已设置null=False,filter中可以省略__isnull=False,直接引用反向关联字段即可触发内连接
  • select_related仅支持正向外键、一对一关联的表连接,反向一对多关联需要通过filter/annotate触发连接,或用prefetch_related预加载数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:36:07