Django 如何执行 LEFT OUTER JOIN 等效操作(即使不存在右对也显示左数据)?
我有两个表:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在什么背景下?如果您想要做的只是打印出来,您可以使用:
或任何您想要的
Product
查询,然后在如下模板中循环:如果您想要更高效的数据库查询,您可以使用
select_lated
(docs):但这会仅在您为
productcode
使用OneToOneField
时有效,不为ForeignKey
:In what context? If all you're looking to do is print this out, you can just use:
or whatever
Product
query you want, then loop through in a template like:If you want a more efficient database query, you can use
select_related
(docs):but this will only work if you're using a
OneToOneField
forproductcode
, not aForeignKey
:根据您设置的内容,产品和覆盖之间的关系是一对多。这意味着对于每个产品,您将(可能)有许多覆盖。
因此,现在您需要考虑要生成什么,这将决定您要如何查询它。
如果您想要一个 Overrides 列表,那么只需查询 Override.objects.all().select_lated()
然后您可以通过遵循外键生成一个 Overrides 列表及其关联的产品数据:
如果您想要一个每个产品都有自己的产品列表覆盖列表,那么您应该查看 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:
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)我相信目前 Django 的 ORM 无法实现这一点,您必须使用
raw
查询。I believe this is not currently possible with the Django's ORM and you have to use a
raw
query.