SQL Server - 使用FROM和JOIN更新不考虑满足JOIN条件的所有行

时间:2015-04-14 16:11:54

标签: sql-server join sql-update

所以,我有两个表T1和T2,其中T1中的主键列“A”具有所有唯一值,T2具有外键“A”,如下所示。

T1
---
A   ConditionMet 
1   0
2   0

T2
---
A    B     C
1    10    5
1    20    20
2    10    10
2    30    0

现在,我希望每当T2中B列的值等于Colum C的值(对于A中的一个特定值)时,将T1表的“ConditionMet”列更新为“1”。我的更新查询如下所示

UPDATE t1
SET
t1.ConditionMet =
   (CASE WHEN t1.ConditionMet = 0 AND t2.B = T2.C THEN 1 END)
FROM
   T1 t1
INNER JOIN T2 t2
WHERE
   t1.A = t2.A

这里我的问题是它没有循环遍历T2的所有行,而是通过值为“A”的第一个记录。假设如果我们在T1中取值“1”,它只会看第一行(1 10 5)而不是T2的第二行(1 20 20)。请帮我理解这个查询有什么问题。在此先感谢!!

3 个答案:

答案 0 :(得分:0)

试试这个......

UPDATE t1
SET
t1.ConditionMet = CASE WHEN t1.ConditionMet = 0 AND t2.B = T2.C 
                        THEN 1 
                   END      
FROM T1 t1
INNER JOIN T2 t2 ON t1.A = t2.A
WHERE NOT EXISTS (SELECT 1 
                  FROM T2
                  WHERE t1.A = A
                   AND B <> C)

答案 1 :(得分:0)

问题在于,当它符合这两个条件时,您无法确定最后一次更新的顺序。这应该做你需要的:

UPDATE t1
SET
    t1.ConditionMet = CASE WHEN T2.a IS NULL THEN 0 ELSE 1 END
FROM
   T1 t1
LEFT JOIN T2 t2
WHERE
   t1.A = t2.A
   and t2.B = t2.C

答案 2 :(得分:0)

问题是你期望得到第一,第二或最后的结果,但是没有定义订单。为什么A = 1的行,其中B = 10是第一个,B = 20是第二个?它实际上是SQL Server最后的更新,但是即便如此,您也无法仅使用ORDER BY来修复查询

您需要编写一个完全确定的查询,也就是说编写一个只更新每行返回1行的选择,这可以可靠地用作更新。我认为我不会像Hugo Kornelis那样,要求UPDATE...FROM被弃用,但如果你不被它抓住,你确实需要了解它。

因此,如果您希望更新T1中的行,其中T2中至少有一行,其中B = C,那么我会使用:

SELECT  T1.A, T1.ConditionMet, NewConditionMet = ISNULL(T2.NewConditionMet, 0)
FROM    T1
        OUTER APPLY
        (   SELECT  TOP 1 NewConditionMet = 1
            FROM    T2
            WHERE   T2.A = T1.A
            AND     T2.B = T2.C
        ) AS T2;

对于您的样本数据,这将返回

A   ConditionMet    NewConditionMet
1   0               1
2   0               1

您需要做的就是将SELECT改编为UPDATE

UPDATE  T1
SET     ConditionMet = CASE WHEN T1.ConditionMet = 0 THEN ISNULL(T2.NewConditionMet, 0) END
FROM    T1
        OUTER APPLY
        (   SELECT  TOP 1 NewConditionMet = 1
            FROM    T2
            WHERE   T2.A = T1.A
            AND     T2.B = T2.C
        ) AS T2;

N.B。这是一个非常罕见的场合,当我认为可以使用TOP而没有ORDER BY时,因为我只返回一个常量值,99%的时间不能使用{{1} }没有TOP


工作示例

ORDER BY