繁体   English   中英

针对相同模型原始查询的多个左连接和左连接转换为Django ORM

[英]Multiple left join and left join against the same model raw query convert to Django ORM

使用Django 1.11

我有以下型号:

class Vendor(Model):

class Product(Model):

class Pricebook(Model):

class Quote(Model):
     vendor = models.ForeignKey(Vendor)

class SKU(Model):
     product = models.ForeignKey(Product)
     pricebook = models.ForeignKey(Pricebook)
     vendor    = models.ForeignKey(Vendor)

class SKUPrice(Model):
    sku = models.ForeignKey(SKU, related_name="prices")

class LineItem(Model):
    quote = models.ForeignKey(Quote, related_name="quote_line_items")
    sku = models.ForeignKey(SKU)

这是适合我的原始查询。

SELECT 
  qli.quantity, 
  sku_source.product_id, 
  sku_dest.id as sku_dest_id, 
  sku_dest_price.id as sku_dest_price_id 
FROM lineitem qli 
INNER JOIN sku sku_source ON 
  qli.sku_id = sku_source.id 
LEFT JOIN sku sku_dest ON 
  sku_dest.pricebook_id = sku_source.pricebook_id AND
  sku_dest.product_id = sku_source.product_id 
LEFT JOIN skuprice sku_dest_price ON
  sku_dest_price.status = 'default' AND 
  sku_dest_price.sku_id = sku_dest.id
WHERE qli.quotation_id = 40 AND 
  qli.quantity > 0 AND 
  sku_dest.vendor_id = 38;

我试过的是:

(the_quote_with_id_as_40
.quotation_line_items
.filter(quantity__gt=0)
.select_related('sku__product')
.values('sku__product__id', 'quantity')
)

这会产生此查询

SELECT "sku"."product_id", "lineitem"."quantity"
FROM "lineitem" 
INNER JOIN "sku" ON ("lineitem"."sku_id" = "sku"."id") 
WHERE ("lineitem"."quotation_id" = 40 AND 
       "lineitem"."quantity" > 0)

这不完全是我想要的。

我当然可以使用原始查询。 但我想知道是否可以使用ORM。 至少,这是为了扩展我的知识。

谢谢。

UPDATE

由于有要求澄清我的模型,我写的是以下内容。

我有一个Quote对象。 它允许许多LineItem对象。 每个LineItem都是SKU和Quote的一对多。

SKU属于Pricebook,产品和供应商。 这些关系的描述也可以从上面的代码中获得。

但为了清楚起见,我将在此重复一遍。

这种安排使得不同供应商可以销售单个相同的产品,但它们将显示为不同的SKU。

这是设计的。

我们的用例是这样的:用户试图将特定Quote的LineItem复制到不同的Quote。

在用户的心目中,他们并不具备理解SKU,LineItem或产品之间差异的复杂性。

这都是他们心目中的产品。 他们只是希望相同的产品出现在具有相同数量的不同报价中。

挑战是这样的。 我们现在有两个行情(要复制的来源报价和要复制的目的地报价)。 两个行情可能都有相同的供应商。 或者他们可能没有。 用户希望我的Django应用程序能够自动满足这两种情况。

所以这意味着我需要在复制之前找出以下内容。

  • LineItem中所述的数量
  • LineItem中所述的产品与SKU相对
  • 找到卖方为目的地报价出售的相应SKU
  • 及其相应的单价

原始查询允许我在单个查询中提取所有4条信息。 这很有效率。

因此,您看到我有别名sku_sourcesku_dest

这就是我的WHERE标准包含3个条件的原因:

  1. 仅复制数量> 0的Source LineItems
  2. 只复制来自特定来源Quote的LineItems
  3. 将仅查看针对特定供应商的SKU(在此情况下为目的地报价的供应商)

有可能:

  1. 同一产品(vis-a-vis SKU)的多个LineItem将出现在同一个源Quote中。

  2. 目标供应商(即目的地报价的供应商)不销售源供应商确实销售的特定产品。 因此我使用LEFT JOIN。 这意味着此特定产品不会重复。

我希望这可以解决问题。

对我来说,你解决问题的方式是不正确的。

您仍在尝试解释查询,而不是您需要的对象。 使用ORM时,您需要停止考虑查询,并开始考虑对象以及它们如何相互进行/交互。 通过这样做,您将把业务逻辑放在代码(模型,管理器等)中而不是在查询中。 您不希望在查询中包含业务逻辑,然后开始思考,确定如何立即创建此查询? 具有哑查询的智能对象更容易被其他人优化和理解,而不是具有哑代码(对象)的智能查询。

从对象开始,编写代码,然后对其进行优化。

如果你向我展示一个未优化的面向对象版本的方法/你需要什么来制作这些副本,我可能会告诉你如何优化它。

在那之前,并不是完全偏离主题,尝试这个查询,但我不能保证你正在寻找的东西:

quote.quotation_line_items.filter(
    quantity__gt=0,
    sku__vendor__sku__vendor=38,
    sku__vendor__sku__product=models.F('sku__product'),
    sku__vendor__sku__pricebook=models.F('sku__pricebook'),
).values(
    'quantity',
    'sku__product_id', # sku source product_id
    'sku__vendor__sku__id', # sku dest id
    'sku__vendor__sku__skuprice__id' # sku dest skuprice id
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM