2016-07-07 93 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”消息?鉴于您似乎没有太多数据,有没有可能将这个问题添加到您的问题中? –