我写了一些SQL来解决我的问题,但还没有准备好。我几天都在尝试不同的查询而没有太多运气。仅供参考我继承了这个DB,所以它可能比我习惯的更先进。
使用桥表FormulaColor在公式和颜色之间存在多对多关系。 FormulaColor具有列(FormulaId,ColorId,Percentage)。
我的业务问题,我们将使用颜色A的所有公式转换为颜色B(1%),C(2.8%)和D(96.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;
答案 0 :(得分:1)
CREATE TABLE [dbo].[ReplacementInfo](
[OldColorId] [int] NULL,
[NewColorID] [int] NULL,
[Percentage] [float] NULL
) ON [PRIMARY]
Declare @KillColor int
Select @KillColor=1
Select FormulaId
into #tmp
from dbo.FormulaColor
where ColorId=@KillColor
Select t1.FormulaId,Coalesce(FC.ColorId,RI.NewColorID) as ColorID,Coalesce(FC.Percentage*RI.Percentage,RI.Percentage) as Percentage
into #tmpInsert
from dbo.ReplacementInfo RI
join #tmp t1 on 1=1
left join dbo.FormulaColor FC on FC.ColorId=RI.NewColorID and t1.FormulaId=FC.FormulaId
Delete FormulaColor
from #tmpInsert
where #tmpInsert.FormulaId=FormulaColor.FormulaId and #tmpInsert.ColorId=FormulaColor.ColorId
Delete FormulaColor where ColorId=@KillColor
insert into FormulaColor
Select * from #tmpInsert
Drop Table #tmp
Drop Table #tmpInsert
答案 1 :(得分:1)
让@DeletedColor
成为要删除的颜色的ID,并@Replacement
替换颜色的表格,如下所示:
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
的百分比计算,以形成替换颜色的最终百分比。
更新刚刚创建的行集中的现有FormulaColor
颜色:
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
;
当然,由于您使用多个语句修改实际表,因此最好在事务中执行修改以确保其原子性。