2016-07-07 96 views
1

我需要更新引用兩個表的表。帶有2個連接的更新表

這是我選擇的代碼來驗證哪些行將被更新。

SELECT * 
FROM txsh AS t1 
     INNER JOIN div AS t2 ON t2.store = t1.ro_no 
     INNER JOIN temp_db AS t3 ON t3.bpn = t1.sku_id 
        AND (t3.div IS NULL OR t3.div = t2.div) 
        AND (t3.s_num IS NULL OR t3.s_num = t1.ro_no) 

enter image description here

這是我加入3代表的結果。列'div'來自表格div,其依賴於ro_no,而'bpn,s_num,created_by'來自表格temp_db。

現在我想從我的選擇代碼中更新所有選定的行。這是我的更新代碼。

UPDATE  txsh 
SET   price = '0' 
FROM   txsh AS t1 
      INNER JOIN temp_db AS t2 ON t1.sku_id = t2.bpn 
      CROSS JOIN div AS t3 
      CROSS JOIN txsh 
WHERE  (t2.div IS NULL OR t3.div = t2.div) 
      AND (t2.s_num IS NULL OR t2.s_num = t1.ro_no) 

我有三個更新實例。這取決於temp_db(BPN,s_num,DIV)

  1. 如果s_num和DIV爲空,更新txsh其中sku_id = BPN
  2. 如果s_num不是null格爲空,更新txsh其中sku_id = BPN和ro_no = s_num
  3. 如果s_num爲空且div不爲空,則更新txsh其中,表div [t2]的sku_id = bpn和[ro_no]的div值等於temp_db的[div]值。

我在想這個錯誤是在實例[3]上。例如[3]有什麼方法糾正我的where子句?

+4

你爲什麼要加入txsh?如果你刪除這個交叉連接並將UPDATE更改爲「t1」,那麼你的查詢是否工作? –

+1

我會更明確地說明這一點。如果你很高興你的第一個查詢按照預期工作,那麼只需從它的開頭刪除「SELECT *」,用「UPDATE txsh SET price ='0'」取代它,你應該很好。一個CROSS JOIN只會返回該表中的每一行,所以你的第二個查詢將更新txsh中的每條記錄,其餘的查詢完全是多餘的,並且無論如何都可能被優化器忽略。 –

+0

兩個完全不同的查詢具有不同的結果是完全正常的。現在如果相同的確定性查詢返回不同的結果,那麼這將是意想不到的。 –

回答

2

好吧,這是越來越太長的對話,所以我把它放到一個答案,而不是...

這是你的原始查詢,稍微重新格式化,使其更易於閱讀:

SELECT 
    t1.* 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
     AND ISNULL(t3.div, t2.div) = t2.div 
     AND ISNULL(t3.s_num, t1.ro_no) = t1.ro_no; 

如果您運行該查詢,它將返回一定數量的行,它可能會從txsh返回每一行,或者由於有兩個約束(INNER JOIN條件),它可能會返回行的子集。

然後,增加的複雜性是那些INNER JOIN可能會從txsh中帶來多條記錄,所以行數可能會比txsh中的行數多。例如,div中可能有10行,其中store = 10,txsh中有一行,其中ro_no = 10(我不知道您的數據,也許這不可能?)。在這種情況下,您可以從txsh中爲10個重複的行存儲每個數據行= 10.

所以我的第一個問題是,這個查詢返回了多少行,這是預期的結果?理想情況下,您沒有重複問題,並且答案是查詢返回的值介於零與txsh中的行數之間。

UPDATE 
    t1 
SET 
    price = '0' 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
     AND ISNULL(t3.div, t2.div) = t2.div 
     AND ISNULL(t3.s_num, t1.ro_no) = t1.ro_no; 

當你運行這個它會告訴你多少行更新,這是相同的行數,你的SELECT查詢返回:作爲

您更新查詢現在應該是簡單?

如果你能回答這兩個問題,那麼我們可以繼續解決這個問題?

好吧,我還是有點懷疑SELECT語句返回7行,UPDATE更新10行......但我們試試這個作爲一個起點。我只是儘可能簡單地寫出你的邏輯。如果這個工作,那麼我們可以重構查詢一下?

UPDATE 
    t1 
SET 
    price = '0' 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
WHERE 
    --Case 1 
    (t3.div IS NULL AND t3.s_num IS NULL) 
    --Case 2 
    OR (t3.div IS NULL AND t3.s_num IS NOT NULL AND t3.s_num = t1.ro_no) 
    --Case 3 
    OR (t3.div IS NOT NULL AND t3.s_num IS NULL AND t3.div = t2.div); 

所以INNER JOIN到temp_db現在就在bbp到sku_id上,因爲在你的三種情況下這是不變的。我將每個案例的其餘邏輯添加到WHERE子句中。

我會嘗試運行這個作爲一個SELECT查詢第一,然後嘗試更新?

+0

感謝您的幫助,但它仍會更新所有行。最初,7行只能更新。查詢更新了所有10行 –

+0

我認爲我的問題在ISNULL(t3.div,t2.div)= t2.div t1包含't2'的'div'值爲'ro_no'。我想更新,其中t3列'div'等於t1(ro_no)'div'值的行。 –

+0

[temp_db]中是否有[div]和[s_num]具有NULL值的行?這似乎是潛在的問題。另外,當你說它更新了所有十行時,你是否檢查了這個,或者當你運行UPDATE時,你是否看到「10 rows affected」消息?鑑於您似乎沒有太多數據,有沒有可能將這個問題添加到您的問題中? –