You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决While循环函数中的重复数据问题:按指定键更新

解决While循环中的重复数据问题(按指定键聚合更新)

问题现状

当前通过While循环动态为临时表添加工序列并更新完成率,但执行后出现重复行,每个工序单独占一行,其他工序列值为NULL:

ID销售订单工单客户材料类型零件厚度需求数量LCT - LASER CUTTINGBNS - BENDING SIMPLEQCT - QUALITY CONTROL
139690000001000071138JG00415389GHH002 - GHHMM MANUFACTURING (PTY) LTDSS304L6.0000003.000000100.00NULLNULL
139691000001000071138JG00415389GHH002 - GHHMM MANUFACTURING (PTY) LTDSS304L6.0000003.000000NULL100.00NULL
139692000001000071138JG00415389GHH002 - GHHMM MANUFACTURING (PTY) LTDSS304L6.0000003.000000NULLNULL0.00

需要将同一工单的所有工序完成率合并到同一行,避免数据重复。

原代码问题分析

  1. 循环更新时,ManufacturingTracking与#temp1仅通过ManufacturingTrackingId关联,若ManufacturingTracking中同一工单对应多条不同工序的记录,会导致#temp1生成重复行。
  2. 逐行循环的方式效率低下,且容易因关联逻辑不严谨导致数据拆分。

最优解决方案:使用动态PIVOT实现行转列

无需使用While循环,直接通过动态透视表一次性完成列生成与数据聚合,自动按指定键(如工单、销售订单)合并数据:

步骤1:准备唯一的基础数据

先确保#temp1中只有核心维度的唯一行,避免初始数据重复:

SELECT 
    ID,
    销售订单,
    工单,
    客户,
    材料类型,
    零件厚度,
    需求数量
INTO #temp1
FROM 你的核心业务表 -- 替换为实际来源表
GROUP BY ID,销售订单,工单,客户,材料类型,零件厚度,需求数量;

步骤2:动态生成透视表SQL

DECLARE @WorkCentreList NVARCHAR(MAX);
DECLARE @PivotSQL NVARCHAR(MAX);

-- 拼接所有需要转为列的工序名称(兼容特殊字符)
SELECT @WorkCentreList = STRING_AGG(QUOTENAME(WorkCentre), ',')
FROM #WorkCentre2;

-- 构建动态透视语句
SET @PivotSQL = N'
SELECT 
    t.ID,
    t.销售订单,
    t.工单,
    t.客户,
    t.材料类型,
    t.零件厚度,
    t.需求数量,
    ' + @WorkCentreList + '
FROM #temp1 t
LEFT JOIN (
    SELECT 
        ManufacturingTrackingId,
        ' + @WorkCentreList + '
    FROM (
        SELECT 
            ManufacturingTrackingId,
            WorkCentre,
            PercentCompleted
        FROM ManufacturingTracking (NOLOCK)
    ) src
    PIVOT (
        MAX(PercentCompleted) -- 若同一工序有多条记录,用MAX/AVG等聚合函数取对应值
        FOR WorkCentre IN (' + @WorkCentreList + ')
    ) pvt
) p ON t.ID = p.ManufacturingTrackingId;';

-- 执行动态SQL
EXEC sp_executesql @PivotSQL;

代码说明

  1. STRING_AGG替代循环逻辑,自动拼接所有工序为合法列名。
  2. PIVOT子句将ManufacturingTracking中的行数据(不同工序完成率)转为列数据,自动按ManufacturingTrackingId聚合,彻底避免重复行。
  3. LEFT JOIN确保核心数据行不会因工序缺失而丢失,对应列显示NULL。

替代方案:修复原有循环逻辑(不推荐,效率低)

若必须保留循环方式,需先确保#temp1行唯一,再执行更新:

-- 第一步:去重#temp1,保留唯一核心行
WITH CTE AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY 工单,销售订单 ORDER BY ID) AS rn
    FROM #temp1
)
DELETE FROM CTE WHERE rn > 1;

-- 第二步:执行循环更新(此时仅匹配唯一行,不会生成重复)
Declare @loop1 int = 0 
Declare @loop2 int = (Select count(*) from #WorkCentre2) 
Declare @SQL varchar(8000) 
Declare @WorkCentre VARCHAR(50)

while @loop1  < @loop2 
begin 
 Set @loop1 = @loop1 + 1 
 SELECT @WorkCentre = WorkCentre from #WorkCentre2 where AutoID = @loop1;
 
 Set @SQL = 'Alter table #temp1 add [' + @WorkCentre + '] varchar(50)' 
 exec(@SQL) 
 
 Set @SQL = ' 
 Update #temp1 set 
  [' + @WorkCentre + '] = mt.PercentCompleted 
 From ManufacturingTracking mt (nolock) 
 inner join #temp1 t
 on t.ID = mt.ManufacturingTrackingId 
 and mt.WorkCentre = ''' + @WorkCentre + '''' 
exec(@SQL)
end

内容的提问来源于stack exchange,提问作者Anton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:58:12