SQL中如何用另一张表数据更新多列?现有语句未达预期求修正
问题分析与解决方案
你的问题出在JOIN后表B返回了两行数据,导致UPDATE操作会执行两次,后一次的更新覆盖了前一次的结果。
举个具体的执行过程:原语句第一次匹配表B中Colz=10的行,会把Col1设为1234,Col2因为CASE条件不满足被设为Null,Col3设为4;第二次匹配Colz=12的行,Col1因为CASE条件不满足被设为Null,Col2设为2345,Col3再次设为4。最终结果里Col1会是Null,和你的预期不符。
正确的更新写法
我们需要先对表B按Id分组,把对应Colz值的Colx聚合出来,再和表A关联更新。这样就能确保每个Id只有一行数据参与更新,彻底避免覆盖问题。
以SQL Server为例,写法如下:
UPDATE a SET Col1 = b.Col1_val, Col2 = b.Col2_val, Col3 = b.Coly_val FROM A a JOIN ( SELECT Id, -- 提取Colz=10对应的Colx,无匹配则保留Null MAX(CASE WHEN Colz = 10 THEN Colx END) AS Col1_val, -- 提取Colz=12对应的Colx,无匹配则保留Null MAX(CASE WHEN Colz = 12 THEN Colx END) AS Col2_val, -- Coly值一致,用MAX/MIN均可保证取到正确值 MAX(Coly) AS Coly_val FROM B GROUP BY Id ) b ON a.Id = b.Id;
思路说明
- 子查询通过
GROUP BY Id把表B中同一Id的多行数据合并成一行 - 用
CASE配合MAX聚合函数,把不同Colz对应的Colx分别提取成独立的列 - 最后用聚合后的结果集更新表A,每个
Id只会执行一次更新,不会出现覆盖情况
执行这个语句后,表A就能得到你想要的预期结果:
| Id | Col1 | Col2 | Col3 |
|---|---|---|---|
| 100 | 1234 | 2345 | 4 |
如果是MySQL等其他数据库,语法会略有差异,但核心思路完全一致:先聚合表B的数据,再关联更新表A。
内容的提问来源于stack exchange,提问作者Harsh




