問題是你期待第一,第二或最後的結果,但沒有定義順序。爲什麼應該A = 1的行,其中B = 10是第一個,B = 20是第二個?它實際上是SQL Server最後一次堅持的更新,但即使如此,你也無法修復你的查詢,只需要一個ORDER BY
你需要編寫一個完全確定性的查詢,也就是說寫一個選擇每行只更新1行,這可以可靠地用作更新。我認爲我不會像雨果·科內利斯那樣呼籲UPDATE...FROM被棄用,但是如果你不被它發現,你需要了解它。
所以,如果你正在尋找那裏是在T2至少一排,其中B = C,那麼我會用更新T1行:
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%的時間是不行的使用TOP
沒有ORDER BY
工作示例
DECLARE @T1 TABLE (A INT, ConditionMet BIT);
DECLARE @T2 TABLE (A INT, B INT, C INT);
INSERT @T1 VALUES (1, 0), (2, 0), (3, 0), (4, 1);
INSERT @T2 VALUES (1, 10, 5), (1, 20, 20), (2, 10, 10), (2, 30, 0), (3, 0, 1), (4, 0, 0);
SELECT * FROM @T1;
UPDATE T1
SET ConditionMet = CASE WHEN T1.ConditionMet = 0 THEN ISNULL(T2.NewConditionMet, 0) END
FROM @T1 AS T1
OUTER APPLY
( SELECT TOP 1 NewConditionMet = 1
FROM @T2 AS T2
WHERE T2.A = T1.A
AND T2.B = T2.C
) AS T2;
SELECT * FROM @T1;
可能我沒有完整的要求。我在T2中有另一列,它表示「運算符」,它可以是「AND」,「OR」或「NULL」。所以,例如,它可能有一個說T2.B(10)= T2.C(5)「AND」T2.B(20)= T2.C(20)的條件。所以,我無法跳過所有行的循環。我可以使用「WHILE」循環來實現這一目標,但希望與像你這樣的專家一起檢查,看看我能否避免這種情況。提前致謝!! – Praveen