所以,我有两个表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)。请帮我理解这个查询有什么问题。在此先感谢!!
答案 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