簡體   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