我有2个表 - 实际和建议 - 如下:
ACTUAL
Id|desc|Allocation|changeBit
1|X|20||
2|y|30||
PROPOSED
Id|desc|Allocation|changeBit
1|X|30|U|
3|z|40|I|
所寻求的结果如下:
1|X|30|U|
2|y|30||
3|z|40|I|
'U'位导致'proposed'中的记录覆盖'actual'。 提议中的'I'位表示需要添加'新'记录。
实现这一目标最优雅的方法是什么?
理想情况下,我希望避免创建临时表,然后插入更新 我正在使用sql-server 2008。
答案 0 :(得分:1)
您应该使用full outer join
加入两个表,然后仅在建议值不存在时使用coalesce
获取实际值:
SELECT COALESCE (p.id, a.id) AS id,
COALESCE (p.desc, a.desc) AS desc,
COALESCE (p.allocation, a.allocation) AS allocation,
COALESCE (p.changebit, a.changebit) AS changebit
FROM actual a
FULL OUTER JOIN proposed p ON a.id = p.id
答案 1 :(得分:1)
我倾向于使用union all
和not exists
来解决这个问题。我发现coalesce()
方法中的列上的isnull()
或full outer join
不够优雅。
select Id, desc, Allocation, changeBit
from proposed
union all
select Id, desc, Allocation, changeBit
from actual a
where not exists (select 1 from proposed p where a.id = p.id);
编辑:
如果您想进行验证,则基本上是:
select Id, desc, Allocation, changeBit
from proposed
where changebit in ('U', 'I')
union all
select Id, desc, Allocation, changeBit
from actual a
where not exists (select 1 from proposed p where a.id = p.id);
真正测试有效的“U”与“I”是更加密集的,似乎是不必要的(并不是原始问题的真正部分)。您可能应该提出另一个问题,并准确解释当非实际记录更新时要执行的操作,或者不存在的记录插入。
答案 2 :(得分:0)
这有点偏离基础,但根据您的上一条语句判断,您似乎正在使用此查询生成INSERT
和UPDATE
语句。由于您使用的是SQL-Server 2008,您是否考虑过使用MERGE
语句在一个命令中执行此操作,而不是三个(查询,插入,更新)?
假设PROPOSED
包含您的更改,您可以执行以下操作:
MERGE ACTUAL AS A
USING PROPOSED AS P
ON A.Id = P.Id
WHEN MATCHED
THEN UPDATE
SET A.Allocation = P.Allocation
WHEN NOT MATCHED
THEN INSERT (Id, [Desc], Allocation)
VALUES (Id, [Desc], Allocation);
使用此功能,您可以删除changeBit
列,因为MERGE
语句会为您提供INSERT
或UPDATE
。