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

如何使用SSIS组件将同ID多行合并为含不同列值的单行

在SSIS中实现相同主键多行数据的列合并

我懂你现在的需求——把相同Mat(PK)的多行数据合并成一行,把各个字段里的非空值对应填充到目标列里。既然已经用SQL搞定了,那我来给你拆解下用SSIS组件怎么实现,有两种实用的方法:

方法一:使用聚合转换(Aggregate Transformation)

这是最直接的方法,适合你这种同一分组下每个字段仅存在一个非空值的场景:

  • 先在数据流中添加数据源组件(比如OLE DB Source),读取你的输入数据。
  • 拖入聚合转换,将数据源的输出连接到聚合转换。
  • 打开聚合转换编辑器:
    • 把Mat(PK)设置为分组依据(Group By),确保按主键分组。
    • 对Activity、EntryDate、Grade这三个字段,分别选择Max或Min聚合函数——因为NULL在聚合计算中会被忽略,而同一分组里每个字段只有一个非空值,Max/Min会精准取到这个有效值。
    • 可以保持每个聚合字段的别名和原字段名一致,方便后续映射到目标表。
  • 最后把聚合转换的输出连接到目标组件(比如OLE DB Destination),就能得到你想要的合并后结果了。

方法二:使用脚本组件(Script Component)作为转换

如果后续遇到更复杂的合并场景(比如同一字段有多个非空值需要拼接),脚本组件会更灵活。针对你的需求,实现步骤如下:

  • 在数据流中添加脚本组件,选择「转换(Transformation)」类型。
  • 连接数据源到脚本组件,打开脚本编辑器:
    1. 在输入列面板,勾选所有需要处理的列:Mat(PK)、Activity、EntryDate、Grade。
    2. 在输出列面板,添加和输入列对应的输出列(名称、类型保持一致)。
    3. 切换到「脚本」选项卡,编辑脚本(以C#为例):
using System.Collections.Generic;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    // 用字典存储每个Mat(PK)对应的合并后数据
    private Dictionary<string, MergedRow> mergedRecords;

    public override void PreExecute()
    {
        base.PreExecute();
        mergedRecords = new Dictionary<string, MergedRow>();
    }

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        string matId = Row.MatPK;
        
        if (!mergedRecords.ContainsKey(matId))
        {
            // 第一次遇到该主键,初始化合并行
            mergedRecords[matId] = new MergedRow
            {
                MatPK = matId,
                Activity = Row.Activity_IsNull ? null : Row.Activity,
                EntryDate = Row.EntryDate_IsNull ? null : Row.EntryDate,
                Grade = Row.Grade_IsNull ? null : Row.Grade
            };
        }
        else
        {
            // 已有该主键的记录,填充非空值
            var existingRow = mergedRecords[matId];
            if (!Row.Activity_IsNull) existingRow.Activity = Row.Activity;
            if (!Row.EntryDate_IsNull) existingRow.EntryDate = Row.EntryDate;
            if (!Row.Grade_IsNull) existingRow.Grade = Row.Grade;
        }
    }

    public override void PostExecute()
    {
        base.PostExecute();
        // 遍历字典,输出所有合并后的行
        foreach (var mergedRow in mergedRecords.Values)
        {
            Output0Buffer.AddRow();
            Output0Buffer.MatPK = mergedRow.MatPK;
            
            // 处理Activity字段
            if (!string.IsNullOrEmpty(mergedRow.Activity))
                Output0Buffer.Activity = mergedRow.Activity;
            else
                Output0Buffer.Activity_IsNull = true;
            
            // 处理EntryDate字段
            if (mergedRow.EntryDate.HasValue)
                Output0Buffer.EntryDate = mergedRow.EntryDate.Value;
            else
                Output0Buffer.EntryDate_IsNull = true;
            
            // 处理Grade字段
            if (!string.IsNullOrEmpty(mergedRow.Grade))
                Output0Buffer.Grade = mergedRow.Grade;
            else
                Output0Buffer.Grade_IsNull = true;
        }
    }

    // 自定义类存储合并后的行数据
    private class MergedRow
    {
        public string MatPK { get; set; }
        public string Activity { get; set; }
        public DateTime? EntryDate { get; set; }
        public string Grade { get; set; }
    }
}
  • 保存脚本后,将脚本组件的输出连接到目标组件即可。

这两种方法都能完美实现你给出的输入输出示例,比如Mat=12的三行数据,合并后会得到Activity=Dev、EntryDate=01/01/2000、Grade=Eng+8的单行结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:37:58