2

我写了一些 SQL 来解决我的问题,但还没有准备好。几天来我一直在尝试不同的查询,但运气不佳。仅供参考,我继承了这个数据库,所以它可能比我习惯的要先进一些。

使用桥表 FormulaColor 在 Formula 和 Color 之间存在多对多关系。FormulaColor 具有列(FormulaId、ColorId、Percentage)。

我的业务问题,我们正在将所有使用颜色 A 的公式转换为颜色 B(1%)、C(2.8%) 和 D(96.2%)。因此,如果一个公式当前使用颜色 A 作为公式的 50%,那么我将为该公式添加一行,颜色为 B,百分比为 0.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;
4

2 回答 2

1

让我们@DeletedColor成为要删除的颜色的 ID,以及@Replacement替换颜色的表,声明如下:

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

解决问题的一种方法是这样的:

  1. 准备要添加到每个公式的实际颜色值:

    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以形成替换颜色的最终百分比。

  2. 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
    ;
    
  3. 将新行集中的颜色插入到不包含这些颜色的公式中:

    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
    ;
    

自然,由于您使用多个语句修改实际表,因此最好在事务中执行修改以确保它们的原子性。

于 2012-10-31T20:09:49.893 回答
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
于 2012-10-31T09:54:20.213 回答