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  

Name1Name2およびName3は主キーです)

同じ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_AllRowsFF_DST_SelectedRows特定のニーズは異なります。スクリプト変換SCR_SelectLastRowは、変換(入力と出力の両方)として構成されます。

ここに画像の説明を入力してください

すべての入力列を選択します(使用タイプを使用ReadOnly):

ここに画像の説明を入力してください

1つの出力を作成し(私は私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();
    }
}

この手法の優れた点の1つは、データを1回のパスで処理でき、ステージングテーブルを使用したり、ソースデータセット全体をメモリに保持したりする必要がないことです。データセットの大きさに応じて、どちらかが重大なパフォーマンスの問題を引き起こす可能性があります。

于 2013-03-04T19:36:23.067 に答える
1

推奨事項1:可能であれば、ソースクエリでこれを実行します。

それが不可能であり、常にColの最大値を選択する必要があると仮定すると、データフローでAggregateコンポーネントを使用できます。

すべての列を集計入力に追加するだけで、操作にはName1、Name2、Name3に[Group By]を選択し、Colに[Maximum]を選択します。

残念ながら、集約コンポーネントは非同期コンポーネントです。つまり、データが流入する間、フロー全体が一時停止します。これは、すべての行で読み取られるまで、各セットの「最大」値がわからないためです。

于 2013-03-04T00:43:38.050 に答える
1

データをグループ化し、最大列値を選択する必要があります。

フロー:

ここに画像の説明を入力してください

データ:

ここに画像の説明を入力してください

骨材要素:

ここに画像の説明を入力してください

結果: ここに画像の説明を入力してください

SQLテーブルを使用していて、クエリを記述できる場合:

SQLFIDDLEExample

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 に答える
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 に答える