2012-05-08 33 views
5

我試圖以類似的方式對這個問題將兩個數據表一起:C#的DataTable內與動態列加入

Inner join of DataTables in C#

我想要得到的輸出是一個「組合拳'表,來自兩個原始表的列。他們都有一個共同的datestamp列。

給出的答案適用於固定列的DataTable,但如果它們是動態創建的,並且可以有任意數量的列,那我該如何加入?

例如

T1 (datestamp, t1Column1, t1Column2, t1ColumnN...) 
T2 (datestamp, t2Column1, t2Column2, t2ColumnN...) 

我想加入到創建以下文件:

J1 (datestamp, t1Column1, t1Column2, t1ColumnN, ..., t2Column1, t2Column2, t2ColumnN...) 

這是可能的嗎?

+0

您可以使用「linq」嗎? –

+0

你能給出一些數據這將是你想出來的結果的例子嗎? –

+0

我不認爲LINQ的是,你需要知道你試圖突入列名的選項。 – finoutlook

回答

7

我發現了一個不依賴循環遍歷列的解決方案。

它使用'合併'方法,我之前已經解僱了,因爲我認爲兩個表都需要相同的結構。

首先,你需要創建兩個數據表的主鍵:

// set primary key 
T1.PrimaryKey = new DataColumn[] { T1.Columns["DateStamp"] }; 
T2.PrimaryKey = new DataColumn[] { T2.Columns["DateStamp"] }; 

然後兩個表添加到數據集這樣的關係,可以說:

// add both data-tables to data-set 
DataSet dsContainer = new DataSet(); 
dsContainer.Tables.Add(T1); 
dsContainer.Tables.Add(T2); 

下一頁添加數據集中兩個關鍵列之間的關係:

// add a relationship between the two timestamp columns 
DataRelation relDateStamp = new DataRelation("Date", new DataColumn[] { T1.Columns["DateStamp"] }, new DataColumn[] { T2.Columns["DateStamp"] }); 
dsContainer.Relations.Add(relDateStamp); 

最後,您現在可以複製第一個數據表到一個新的「組合拳」的版本,然後合併在第二:

// populate combined data 
DataTable dtCombined = new DataTable(); 
dtCombined = T1.Copy(); 
dtCombined.Merge(T2, false, MissingSchemaAction.Add); 

注:合併方法需要第二個參數是假的,否則它複製結構,但第二的不是數據表。

這再結合下面的表格:

T1 (2012-05-09, 111, 222) 
T2 (2012-05-09, 333, 444, 555) 

成基於主鍵的組合版本:

J1 (2012-05-09, 111, 222, 333, 444, 555) 
1

我認爲你可以修改鏈接問題中的答案,使用index of the column而不是列名。或者你可以循環遍歷每一行中的項目,如下所示:

foreach(DataRow row in table.Rows) 
{ 
    foreach(DataColumn column in table.Columns) 
    { 
     object value = row[column]; // add this to your combined table 
    } 
} 
+0

謝謝 - 我希望避免通過所有列循環,因爲我已經有幾個嵌套的循環來建立原始表。如果表中的數據有很多不同的日期/鍵,這可能會變得非常複雜。 – finoutlook

1

厭倦了看到的,畢竟這些內部連接功能,唐」 t可靠地模擬SQL,我決定在這裏做我自己的:

private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn) 
{ 
    DataTable result = new DataTable(); 
    foreach (DataColumn col in t1.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataColumn col in t2.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataRow row1 in t1.Rows) 
    { 
     var joinRows = t2.AsEnumerable().Where(row2 => 
      { 
       foreach (var parameter in joinOn) 
       { 
        if (!parameter(row1, row2)) return false; 
       } 
       return true; 
      }); 
     foreach (DataRow fromRow in joinRows) 
     { 
      DataRow insertRow = result.NewRow(); 
      foreach (DataColumn col1 in t1.Columns) 
      { 
       insertRow[col1.ColumnName] = row1[col1.ColumnName]; 
      } 
      foreach (DataColumn col2 in t2.Columns) 
      { 
       insertRow[col2.ColumnName] = fromRow[col2.ColumnName]; 
      } 
      result.Rows.Add(insertRow); 
     } 
    } 
    return result; 
} 

一門考試您可能會如何使用它:

var test = JoinDataTables(transactionInfo, transactionItems, 
       (row1, row2) => 
       row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID")); 
+0

幹得好。有沒有辦法將其修改爲能夠在多個「加入」條件之間指定AND或OR運算符? – Igor