Django如何做LEFT OUTER JOIN等效(即使没有正确的对存在,也显示左数据)?

时间:2011-10-05 20:43:51

标签: django django-views django-orm

我有两张桌子:

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都有一个名为Customer的列。 Override类在“customerid”和“code”上具有UNIQUE TOGETHER(因此每个客户对每个代码进行一次覆盖)。

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

ORM查询如下所示: pricelist = Product.objects.select_related()。filter(Override__customerid = 1)

但是这只会进行常规连接(省略任何与Override不配对的产品),我想要LEFT OUTER JOIN显示Product表中的所有内容,加入任何Overrides(如果存在或为NULL)

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

3 个答案:

答案 0 :(得分:0)

在什么情况下?如果你想做的就是打印出来,你可以使用:

products = Product.objects.all()

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

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

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

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

但如果您使用OneToOneField productcode a ForeignKey >

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

答案 1 :(得分:0)

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

所以现在你想要考虑你想要生成什么,这将决定你想如何查询它。

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

然后,您可以按照外键生成覆盖列表及其关联的产品数据:

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

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

答案 2 :(得分:0)

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