2013-03-04 44 views
2

我有象以下行數據:用相同的密鑰刪除行

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 

Name1Name2Name3是主鍵)

如何從該組數據中移除所述第一行使用相同的3個主鍵? (離開只有該組的最後一行)

I.e.從上面的結果將是:

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

回答

2

假設你的源數據以正確的順序,你想在每一組中的最後記錄,沒有任何失可以處理這種情況的機箱轉換。但是,腳本轉換可以很容易地處理它。

這裏的一個樣本數據流:

enter image description here

我使用FF_SRC_AllRowsFF_DST_SelectedRows作爲平面文件源和目的地(分別)爲簡單起見,使用您提供的樣品的數據;您的具體需求會有所不同。腳本轉換SCR_SelectLastRow被配置爲轉換(輸入和輸出):

enter image description here

選擇的所有輸入的字段(使用類型ReadOnly):

enter image description here

創建一個輸出(我將它命名爲OutgoingRows,但您可以隨意命名它),並將SynchronousInputID屬性設置爲None。這會讓你的腳本過濾出你不想要的行。

enter image description here

添加對應的輸入列輸出列:

enter image description here

而且沿着這些線路使用代碼:

/* 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(); 
    } 
} 

關於這項技術的一個好處是,它允許您一次處理數據,不需要使用臨時表和ke將整個源數據集設置在內存中。根據您的數據集有多大,這些可能會導致重大的性能問題。

+0

謝謝你的迴應!我用埃德蒙施韋普的答案,我的程序工作!再次感謝。 – Albert 2013-04-16 00:57:20

1

建議#1:如果可能的話在源查詢中執行此操作。

假設這是不可能的,假設您始終希望選擇Col的最大值,那麼可以在數據流中使用Aggregate組件。

只是對所有列添加到總投入,併爲操作選擇「分組依據」爲1,名稱和NAME3「最大」爲上校

不幸的是,總的成分是異步組件 - 意味着您的整個流程將在數據流入時暫停,因爲它不會知道每個組的「最大」值,直到它在每一行中讀取爲止。

+0

真;然而,OP期望獲得* last *行,而不是具有最大值的行。 – 2013-03-04 19:43:19

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的是表名

+0

我喜歡使用'PARTITION BY'。然而,OP要求* last *行,而不是'col'的*最大*值。此外,儘管在OP環境中有一個SQL Server數據庫的可能性相當好,但最初的問題根本沒有提到數據庫,更不用說支持「PARTITION BY」的數據庫了。 – 2013-03-04 19:47:04

0

您需要對您的數據進行分組並選擇最大Col值。

FLOW:

enter image description here

數據:

enter image description here

骨料元件:

enter image description here

結果: enter image description here

如果您使用的是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 |