【问题标题】:Implementing LEFT JOIN explicitly in Django在 Django 中显式实现 LEFT JOIN
【发布时间】:2020-02-01 18:29:47
【问题描述】:

我已经浏览了关于 Django 和 LEFT JOIN 问题的无尽帖子,但没有找到任何人在 2.2 版本的 Django 中提供解决方案。虽然在过去的几年里似乎有办法解决这个问题,但 Django 团队似乎已经关闭了人们用来实现最简单但必要的查询的所有机制——左连接。 这是我正在尝试做的一个简单的示例(这是一个反映现实世界场景的简单示例,因此请不要提供重新设计模型的方法.. . 我想要的只是 SQL 中古老的 LEFT JOIN .... 就这么简单):

from django.db import models
from uuid import uuid4
class People(models.Model):
    id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
    name = models.CharField(max_length=255)


class Book(models.Model):
    id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
    name = models.CharField(max_length=255)
    author = models.ForeignKey(People)
    publisher = models.ForeignKey(People, on_delete=models.PROTECT, null=True)

我将如何获得显示所有书籍出版商如果有出版商的输出(否则只是空白)

Books.objects.filter(Q(publisher__isnull=True | Q(publisher__isnull=False)

... 产生一个 INNER JOIN 显然只会显示分配了出版商的书籍。 我正在寻找的查询将是以下形式: select * from book LEFT JOIN people ON book.publisher_id=people.id

... 还是我必须求助于原始 SQL 来满足这个最简单的要求?

【问题讨论】:

    标签: django left-join


    【解决方案1】:

    您可以在这里执行.select_related(..) [Django-doc]

    Book.objects.select_related('publisher')

    这将同时获取Book 数据和相关的Publisher(如果存在)。所以some_book.publisher 其中some_book 来自这个查询集,不会导致额外的查询来获取发布者。查询如下所示:

    SELECT book.id, book.name, book.author_id, book.publisher_id,
           people.id, people.name
    FROM book
    LEFT OUTER JOIN people ON book.publisher_id = people.id
    

    【讨论】:

    • 我看到select_related执行的是内连接,但是这里是左外连接。是因为 ForeignKey 中的null=True 还是我遗漏了什么?
    • @NalinDobhal:它通常执行左外连接。但是对于不可为空的字段,它可以优化为 INNER JOIN :)。因此,我认为严格来说是相反的。但归根结底是一样的 :) 您可以使用 print(Book.objects.select_related('publisher').query) 检查它,它确实会产生 LEFT OUTER JOIN
    • 好吧,我应该在发布之前实际运行我的简化模型并进行测试......在我的“现实生活”模型中,该模型具有另一个模型的外键,与上述关系中描述的完全一样,相同select_related() 方法仍然会产生一个 INNER JOIN ...将尝试找出导致 Django 决定不对我的案例使用 LEFT JOIN 的原因
    • @ChristopherBroderick:通常那是因为 Django ORM 发现了一个不需要使用 LEFT JOIN 的东西。因此,将 LEFT JOIN 转换为 INNER JOIN 是一种“优化”。这是一个正当的理由,或者是一个错误。
    • 我自己的愚蠢...... ForeignKey 字段是必需的而不是可选的,因此 LEFT JOIN 效率低下且不必要
    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2021-10-06
    • 2017-04-04
    • 2011-08-22
    • 2017-02-20
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多