Django 如何执行 LEFT OUTER JOIN 等效操作(即使不存在右对也显示左数据)?

发布于 2024-12-08 12:34:28 字数 1149 浏览 1 评论 0原文

我有两个表:

class Product(models.Model):
    code = models.ForeignKey(Product)
    regularprice = models.DecimalField (max_digits=8, decimal_places=2)

class Override(models.Model):
    productcode = models.ForeignKey(Product)
    specialprice = models.DecimalField (max_digits=8, decimal_places=2)


Data Example
============
Product
Code    RegularPrice
C101        1.25
C102        2.50
C103        3.00

Override
ProductCode SpecialPrice
C102        1.50

我想做相当于左外连接的操作。我想要实现的结果集是:

Code    RegularPrice     SpecialPrice
C101        1.25        NULL
C102        2.50          1.50
C103        3.00         NULL

我将如何做到这一点?


编辑:我正在尝试实现一个基本价目表,并具有可选的覆盖值。生成基本价格,并附加任何覆盖值(如果不存在则为 NULL)。

非常抱歉,但我确实遗漏了这个问题的一个重要元素,认为这会让它变得更简单。每个覆盖都有一个名为“客户”的列。 Override 类在“customerid”和“code”上具有唯一性(因此每个客户的每个代码都有一个覆盖)。

我希望生成所有产品的价目表+如果特定客户存在任何覆盖,它们将与相应的产品线一起显示。

ORM 查询如下所示: Pricelist = Product.objects.select_lated().filter(Override__customerid=1)

但这仅执行常规联接(省略任何未与覆盖配对的产品),我想要一个 LEFT OUTER JOIN 显示 Product 表中的所有内容,以及任何覆盖连接(如果存在,或 NULL)

非常感谢您提供的任何帮助!

I have two tables:

class Product(models.Model):
    code = models.ForeignKey(Product)
    regularprice = models.DecimalField (max_digits=8, decimal_places=2)

class Override(models.Model):
    productcode = models.ForeignKey(Product)
    specialprice = models.DecimalField (max_digits=8, decimal_places=2)


Data Example
============
Product
Code    RegularPrice
C101        1.25
C102        2.50
C103        3.00

Override
ProductCode SpecialPrice
C102        1.50

I want to do equivalent of a left outer join. The result set I want to achieve would be:

Code    RegularPrice     SpecialPrice
C101        1.25        NULL
C102        2.50          1.50
C103        3.00         NULL

How would I do this?


EDIT: I am trying to achieve a base price list, with optional override values. The base prices are generated, with any override values appended alongside (or NULL if none present).

Very sorry but I did leave out an important element of this question thinking it would make it simpler. Each Override has a column called Customer. The Override class has UNIQUE TOGETHER on "customerid" and "code" (so one override per code, per customer).

I wish to generate a PriceList of all Products + if any Overrides are present for the particular Customer they will be shown alongside the corresponding Product line.

The ORM query looks like this:
pricelist = Product.objects.select_related().filter(Override__customerid=1)

But this only does a regular join (omitting any Product that isnt paired with an Override), I want a LEFT OUTER JOIN displaying everything in the Product table, with any Overrides joined (if present, or NULL)

Many thanks for any help you can offer!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不必你懂 2024-12-15 12:34:28

在什么背景下?如果您想要做的只是打印出来,您可以使用:

products = Product.objects.all()

或任何您想要的 Product 查询,然后在如下模板中循环:

{% for product in products %}
    {{product.code}}
    {{product.regularprice}}
    {{product.override.specialprice|default:"NULL"}}
{% endfor %}

如果您想要更高效的数据库查询,您可以使用 select_lateddocs):

products = Product.objects.select_related('override')

但这会在您为 productcode 使用 OneToOneField 时有效,ForeignKey

class Override(models.Model):
    productcode = models.OneToOneField(Product)

In what context? If all you're looking to do is print this out, you can just use:

products = Product.objects.all()

or whatever Product query you want, then loop through in a template like:

{% for product in products %}
    {{product.code}}
    {{product.regularprice}}
    {{product.override.specialprice|default:"NULL"}}
{% endfor %}

If you want a more efficient database query, you can use select_related (docs):

products = Product.objects.select_related('override')

but this will only work if you're using a OneToOneField for productcode, not a ForeignKey:

class Override(models.Model):
    productcode = models.OneToOneField(Product)
墨小沫ゞ 2024-12-15 12:34:28

根据您设置的内容,产品和覆盖之间的关系是一对多。这意味着对于每个产品,您将(可能)有许多覆盖。

因此,现在您需要考虑要生成什么,这将决定您要如何查询它。

如果您想要一个 Overrides 列表,那么只需查询 Override.objects.all().select_lated()

然后您可以通过遵循外键生成一个 Overrides 列表及其关联的产品数据:

o = Override.objects.all()[0]
o.product.regularprice

如果您想要一个每个产品都有自己的产品列表覆盖列表,那么您应该查看 itertools grouby 函数(或者如果您在模板中,请使用 django regroup 标记)

Based on what you've set up the relationship between Product and Override is one to many. Which means that for every Product you'll have (potentially) many Overrides.

So now you'll want to think about what you want to generate and that will determine how you want to query this.

If you want a list of Overrides then simply query Override.objects.all().select_related()

Then you can generate a list of Overrides and their associated Product's data by following the foreignkeys:

o = Override.objects.all()[0]
o.product.regularprice

If you want a list of products each with their own list of overrides then you should look at the itertools grouby function (or if you're in a template use the django regroup tag)

终陌 2024-12-15 12:34:28

我相信目前 Django 的 ORM 无法实现这一点,您必须使用 raw 查询。

I believe this is not currently possible with the Django's ORM and you have to use a raw query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文