5

我有如下行的数据:

Name1  Name2  Name3  Col  
aaa    bbb    ccc    ...  
abc    ddd    ddd    1  
abc    ddd    ddd    2  
abc    ddd    ddd    3  
fff    fff    fff    ...  
ggg    ggg    hhh    4  
ggg    ggg    hhh    5  

( Name1,Name2Name3是主键)

如何从具有相同 3 个主键的数据集中删除第一行?(只留下集合的最后一行)

即上述结果将是:

Name1  Name2  Name3  Col  
aaa    bbb    ccc    ...  
abc    ddd    ddd    3  
fff    fff    fff    ...  
ggg    ggg    hhh    5  
4

4 回答 4

5

假设您的源数据顺序正确,并且您想要每组中的最后一条记录,则没有任何开箱即用的转换可以处理这种情况。但是,脚本转换可以相当容易地处理它。

这是一个示例数据流:

在此处输入图像描述

为简单起见,我使用FF_SRC_AllRows和作为平面文件源和目标(分别),使用您提供的示例数据;FF_DST_SelectedRows您的具体需求会有所不同。脚本转换SCR_SelectLastRow配置为转换(输入和输出):

在此处输入图像描述

选择所有输入列(使用类型ReadOnly):

在此处输入图像描述

创建一个输出(我命名为 mine OutgoingRows,但您可以随意命名),并将SynchronousInputID属性设置为None. 这将使您的脚本过滤掉您不想要的行。

在此处输入图像描述

添加与输入列对应的输出列:

在此处输入图像描述

并使用以下代码:

/* Microsoft SQL Server Integration Services Script Component
*  Write scripts using Microsoft Visual C# 2008.
*  ScriptMain is the entry point class of the script.*/

using System;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    class IncomingRowData
    {
        public string Name1;
        public string Name2;
        public string Name3;
        public string Col;
        public IncomingRowData(IncomingRowsBuffer Row)
        {
            Name1 = Row.Name1;
            Name2 = Row.Name2;
            Name3 = Row.Name3;
            Col = Row.Col;
        }
        public bool KeysDiffer(IncomingRowData other)
        {
            return (Name1 != other.Name1
                || Name2 != other.Name2
                || Name3 != other.Name3);
        }
        public void WriteToOutputBuffer(OutgoingRowsBuffer Row)
        {
            Row.AddRow();
            Row.Name1 = Name1;
            Row.Name2 = Name2;
            Row.Name3 = Name3;
            Row.Col = Col;
        }
    }

    private IncomingRowData _previousRow;

    public override void IncomingRows_ProcessInputRow(IncomingRowsBuffer Row)
    {
        if (_previousRow == null)
        {
            _previousRow = new IncomingRowData(Row);
        }
        IncomingRowData currentRow = new IncomingRowData(Row);
        if (currentRow.KeysDiffer(_previousRow))
        {
            _previousRow.WriteToOutputBuffer(this.OutgoingRowsBuffer);
        }
        _previousRow = currentRow;
    }

    public override void FinishOutputs()
    {
        if (_previousRow != null)
        {
            _previousRow.WriteToOutputBuffer(this.OutgoingRowsBuffer);
        }
        base.FinishOutputs();
    }
}

这种技术的一个好处是它允许您一次处理数据,并且不需要使用临时表,也不需要将整个源数据集保存在内存中。根据您的数据集有多大,其中任何一个都可能导致严重的性能问题。

于 2013-03-04T19:36:23.067 回答
1

建议 #1:尽可能在源查询中执行此操作。

假设这是不可能的,并且假设您始终希望选择 Col 的最大值,您可以在数据流中使用 Aggregate 组件。

只需将所有列添加到聚合输入中,对于操作,为 Name1、Name2 和 Name3 选择“Group By”,为 Col 选择“Maximum”。

不幸的是,聚合组件是一个异步组件 - 这意味着您的整个流程将在数据流入其中时暂停,因为在每一行中读取它之前它不会知道每个集合的“最大值”值。

于 2013-03-04T00:43:38.050 回答
1
SELECT name1, 
       name2, 
       name3, 
       col 
FROM   (SELECT name1, 
               name2, 
               name3, 
               col, 
               Max(rn) 
                 over ( 
                   PARTITION BY name1, name2, name3 ) AS max_rn, 
               rn 
        FROM   (SELECT name1, 
                       name2, 
                       name3, 
                       col, 
                       Row_number() 
                         over ( 
                           PARTITION BY name1, name2, name3 
                           ORDER BY col ) AS rn 
                FROM   test1)) 
WHERE  max_rn = rn; 

你可以试试这个 test1 是表名

于 2013-03-04T01:52:02.887 回答
1

您需要对数据进行分组并选择最大 Col 值。

流动:

在此处输入图像描述

数据:

在此处输入图像描述

聚合元素:

在此处输入图像描述

结果: 在此处输入图像描述

如果您使用 SQL Table 并且可以编写查询:

SQLFIDDLE示例

SELECT Name1, Name2, Name3, MAX(Col) Col
FROM Table1
GROUP BY Name1, Name2, Name3

结果:

| NAME1 | NAME2 | NAME3 | COL |
-------------------------------
|   aaa |   bbb |   ccc | ... |
|   abc |   ddd |   ddd |   3 |
|   fff |   fff |   fff | ... |
|   ggg |   ggg |   hhh |   5 |
于 2013-03-05T06:49:29.400 回答