Django ORM 语法 ↔ SQL 连接类型对照表

Django ORM ↔ SQL JOIN 对照表(工程版)

结论基于 Django 官方 ORM 行为 + 实际生成 SQL


一、最常见的 6 种情况(你日常 90% 会遇到)

Django ORM 写法SQL JOIN 类型条件位置说明
annotate(Count('rel'))LEFT OUTER JOINHAVING保留 0 条关联记录
annotate(Count('rel')).filter(count=0)LEFT OUTER JOINHAVING查“没有关联记录”的对象
filter(rel__field=value)INNER JOINWHERE只保留有关联记录
filter(rel__isnull=False)INNER JOINWHERE等价于存在关联
filter(rel__isnull=True)LEFT OUTER JOINWHERE查“没有关联”的对象
exclude(rel__field=value)LEFT OUTER JOINWHERE + NOTDjango 为保持语义会用 LEFT


二、ForeignKey 正向 / 反向(你刚才讨论的核心)

正向 ForeignKey(Book → Author)

Book.objects.select_related('author')
项目行为
JOININNER JOIN
原因外键字段非空(默认)
特点单条 SQL


反向 ForeignKey(Author → Book)

Author.objects.prefetch_related('book_set')
项目行为
JOIN❌ 无 JOIN
查询数2 条 SQL
原因Python 层合并


三、annotate 场景(非常重要)

统计关联数量

Author.objects.annotate(book_count=Count('book_set'))
项目行为
JOINLEFT OUTER JOIN
GROUP BY主键
目的保留 book_count = 0


统计 + 过滤

Author.objects.annotate(book_count=Count('book_set')).filter(book_count__gt=3)
项目行为
JOINLEFT OUTER JOIN
条件HAVING
语义按统计结果过滤


四、isnull 是 JOIN 选择的分水岭(必背)

查“有关联”的对象

Author.objects.filter(book__isnull=False)
项目行为
JOININNER JOIN
原因必须存在 book


查“没有关联”的对象

Author.objects.filter(book__isnull=True)
项目行为
JOINLEFT OUTER JOIN
WHEREbook.id IS NULL


五、exclude 的特殊性(很多人会踩坑)

Author.objects.exclude(book__price__gt=100)
项目行为
JOINLEFT OUTER JOIN
原因Django 需要保留“没有 book 的 author”


六、select_related vs prefetch_related(JOIN 视角)

ORMJOIN适用关系
select_relatedINNER JOINFK / OneToOne
prefetch_related无 JOIN反向 / M2M


七、超短记忆口诀(工程必背)

统计 → LEFT JOIN普通过滤 → INNER JOINisnull=True → LEFT JOINisnull=False → INNER JOINprefetch → 不 JOIN


八、提醒(非常重要)

Django ORM 没有 RIGHT JOIN / FULL JOIN

如果你需要:

  • FULL OUTER JOIN
  • RIGHT JOIN

👉 必须:

  • raw()
  • 数据库视图
  • 或重构模型 / 查询逻辑
文章标签:

评论(0)