将插入选择转换为更新的SQL

将插入选择转换为更新的SQL,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我编写了一些SQL来解决我的问题,但它还没有完全准备好。几天来,我一直在尝试不同的问题,但运气不好。仅供参考,我继承了这个数据库,因此它可能比我以前使用的更先进 使用桥接表FormulaColor,公式和颜色之间存在多对多关系。FormulaColor包含FormulaId、ColorId和Percentage列 我的业务问题是,我们正在将所有使用颜色A的配方转换为颜色B1%、C2.8%和D96.2%。因此,如果一个公式当前使用颜色a作为公式的50%,那么我将为该公式添加一行,B颜色的百分比为.

我编写了一些SQL来解决我的问题,但它还没有完全准备好。几天来,我一直在尝试不同的问题,但运气不好。仅供参考,我继承了这个数据库,因此它可能比我以前使用的更先进

使用桥接表FormulaColor,公式和颜色之间存在多对多关系。FormulaColor包含FormulaId、ColorId和Percentage列

我的业务问题是,我们正在将所有使用颜色A的配方转换为颜色B1%、C2.8%和D96.2%。因此,如果一个公式当前使用颜色a作为公式的50%,那么我将为该公式添加一行,B颜色的百分比为.5%,C颜色的百分比为1.4%,D颜色的百分比为48.1%

但问题是,一个包含颜色a的给定公式可能已经包含一个或多个颜色B、C或D。在这种情况下,我需要通过简单地添加上面计算的内容来更新百分比

到目前为止,我拥有的实际sql如下所示*请注意,这仅用于处理1种新颜色ColorId=2594

INSERT INTO FormulaColor (FormulaId, ColorId, Percentage) 
SELECT FormulaId, 2594 as ColorId, round((.01*FormulaColor.Percentage),2) as Percentage
FROM FormulaColor WHERE ColorId=2595;
DELETE FROM FormulaColor WHERE ColorId = 2595;
我在想我需要的是使用使用@rowscount的upsert方法吗?如果是这样的话,我不知道如何进行更新,将计算出的金额添加到百分比中

任何帮助或资源都将不胜感激

更新

我最终使用了Andriy M的解决方案。如果它能帮助其他人,我将发布我使用的实际SQL

DECLARE @DeletedColor int;
DECLARE @Replacement TABLE (ColorId int, Percentage float);

-- old ColorId getting replaced
SET @DeletedColor = 2595

-- new ColorId's and the percentages needed to recalculate
INSERT INTO @Replacement (ColorId, Percentage) VALUES (2594, .01)
INSERT INTO @Replacement (ColorId, Percentage) VALUES (2521, .028)
INSERT INTO @Replacement (ColorId, Percentage) VALUES (2533, .962)

SELECT
  fc.FormulaId,
  r.ColorId,
  Percentage = round(fc.Percentage * r.Percentage, 2)
INTO #FormulaColor
FROM FormulaColor fc
CROSS JOIN @Replacement r
WHERE fc.ColorId = @DeletedColor
;

UPDATE old
SET old.Percentage = old.Percentage + new.Percentage
FROM FormulaColor old
INNER JOIN #FormulaColor new
 ON old.FormulaId = new.FormulaId
AND old.ColorId   = new.ColorId
;

INSERT INTO FormulaColor (FormulaId, ColorId, Percentage)
SELECT new.FormulaId, new.ColorId, new.Percentage
FROM #FormulaColor new
LEFT JOIN FormulaColor old
 ON old.FormulaId = new.FormulaId
AND old.ColorId   = new.ColorId
WHERE old.FormulaId IS NULL
;

DELETE FROM FormulaColor WHERE ColorId = @DeletedColor;
将@DeletedColor作为要删除颜色的ID,@Replacement作为替换颜色表,声明如下:

DECLARE @DeletedColor int;
DECLARE @Replacement TABLE (ColorId int, Percentage float);
解决问题的一种方法是:

DECLARE @DeletedColor int;
DECLARE @Replacement TABLE (ColorId int, Percentage float);
准备要添加到每个配方中的实际颜色值:

SELECT
  fc.FormulaId,
  r.ColorId,
  Percentage = fc.Percentage * r.Percentage
INTO #FormulaColor
FROM FormulaColor fc
CROSS JOIN @Replacement r
WHERE fc.ColorId = @DeletedColor
;
这是为包含@DeletedColor的每个公式创建替换颜色列表。替换表中每种替换颜色的指定百分比由每种配方的@DeletedColor的百分比构成替换颜色的最终百分比

从刚创建的行集合更新现有公式颜色:

UPDATE old
SET old.Percentage = old.Percentage + new.Percentage
FROM FormulaColor old
INNER JOIN #FormulaColor new
 ON old.FormulaId = new.FormulaId
AND old.ColorId   = new.ColorId
;
将新行集合中的颜色插入不包含这些颜色的公式:

INSERT INTO FormulaColor (FormulaId, ColorId, Percentage)
SELECT new.FormulaId, new.ColorId, new.Percentage
FROM #FormulaColor new
LEFT JOIN FormulaColor old
 ON old.FormulaId = new.FormulaId
AND old.ColorId   = new.ColorId
WHERE old.FormulaId IS NULL
;

当然,由于您要使用多条语句修改实际表,最好在事务中执行修改,以确保其原子性。

旁注:1=1上的加入tmp t1相当于交叉加入tmp t1,我只是想在您不知道的情况下让您知道。谢谢,我将在接下来的几天内对此进行测试,如果有效,请标记您的答案!我必须做一些研究来了解发生了什么,以及如何使用它,比如如何设置@depentedColor。然而,它最终似乎运作良好。非常感谢。
INSERT INTO FormulaColor (FormulaId, ColorId, Percentage)
SELECT new.FormulaId, new.ColorId, new.Percentage
FROM #FormulaColor new
LEFT JOIN FormulaColor old
 ON old.FormulaId = new.FormulaId
AND old.ColorId   = new.ColorId
WHERE old.FormulaId IS NULL
;