SQL Update语句 - 为什么这样做?

时间:2018-03-27 16:47:21

标签: sql sql-server sql-update

我写了一个可以工作并完成我想要的查询,但我无法弄清楚为什么逻辑工作正常。我无法分享确切的表格,因为信息很敏感,但我会在下面重新创建。

Table_A有三列:

Employee_ID, 
Condition, 
B_Confirmed_Flag

Table_B有两列:

Employee_ID, 
Condition

我的目标是编写一个更新语句,只要Employee_ID - >,就会将Table_A中的B_Confirmed_Flag更新为1。条件组合存在于表__B中。

更新声明:

 UPDATE TABLE_A
    SET B_Confirmed_Flag = 1
    FROM TABLE_A
    WHERE TABLE_A.Condition IN (SELECT TABLE_B.CONDITION
                                FROM TABLE_B
                                WHERE TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID)

此更新声明似乎有效,但我对逻辑感到困惑。我会认为,使用此更新语句,我将不必要地标记某些行,其中Table_B中的多个Employee_ID在Condition列中具有相同的值。但是,查询对我有用。

谢谢!

3 个答案:

答案 0 :(得分:2)

要回答它是如何工作的,请按照与此类似的方式细分查询: 对于表A中的每条记录,子查询表B中员工ID匹配的所有记录。然后,如果表A中的记录具有子查询中存在的条件,则更新发生。有效地为您提供employeeID和Condition的连接条件。

正如其他人已经回答的那样,重写您的查询将更容易阅读,并可能表现更好。

答案 1 :(得分:2)

让我们假设您有这样的虚拟数据:

CREATE TABLE #table_A (Employee_ID INT, 
Condition VARCHAR(1), 
B_Confirmed_Flag BIT
)

CREATE TABLE #table_B (Employee_ID INT, 
Condition VARCHAR(1)
)

INSERT INTO #table_A (Employee_ID, Condition, B_Confirmed_Flag)
VALUES 
(1, 'A', 0),
(2, 'A', 0),
(3, 'A', 0),
(4, 'B', 0),
(5, 'B', 0),
(6, 'B', 0),
(7, 'B', 0)

INSERT INTO #table_B (Employee_ID, Condition)
VALUES 
(1, 'A'),
(3, 'A'),
(5, 'B'),
(6, 'B')

如果您运行这两个查询并启用执行计划,您将看到差异。

select * 
FROM #TABLE_A
WHERE #TABLE_A.Condition IN (SELECT #TABLE_B.CONDITION
                            FROM #TABLE_B
                            WHERE #TABLE_B.EMPLOYEE_ID = #TABLE_A.EMPLOYEE_ID)
select * 
FROM #TABLE_A
WHERE #TABLE_A.Condition IN (SELECT #TABLE_A.CONDITION
                            FROM #TABLE_A
                            WHERE #TABLE_A.EMPLOYEE_ID IN (1,4))

第一个是你的,第二个是样本。听起来你期望你的查询像第二个一样工作。如果查询的IN部分应返回应更新table_A中所有记录的值,为什么不呢?如果检查执行计划并查看嵌套循环谓词,则可以看到查询正在查看条件以及员工ID。这就是为什么更新只更新它在表B中找到的员工以及他们的状况。

enter image description here

enter image description here

答案 2 :(得分:1)

它的工作原理是因为逐行处理更新

这应该更有效率

UPDATE TABLE_A
SET B_Confirmed_Flag = 1
FROM TABLE_A
WHERE exists ( SELECT 1 
                 FROM TABLE_B
                 WHERE TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID 
                   and TABLE_B.Condition   = TABLE_A.CONDITION 
             ) 
 and (B_Confirmed_Flag <> 1 or B_Confirmed_Flag is null) 

如果那些是pk那么

UPDATE TABLE_A
SET B_Confirmed_Flag = 1
FROM TABLE_A
JOIN TABLE_B
  ON TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID 
 and TABLE_B.Condition   = TABLE_A.CONDITION 
 and (B_Confirmed_Flag <> 1 or B_Confirmed_Flag is null)