2016-08-18 20 views
0

我需要將C#上的數據表與一個公用列進行合併/連接。如何在C#中使用普通列完成2個或多個數據表的完全外部聯接

我知道很多例子和關於同一主題的問題。我還沒有找到任何回答我的問題。

以下是我正在使用的代碼。

該代碼只允許基於datatable數據的一個公共列。我需要一個公共列,但需要考慮其他「帳戶號」可能會在另一個數據表中使用並將其添加到公共列中。

此外代碼只允許合併2個數據表。我需要合併31個數據表,合併1個數據表。

我對這個月的每一天的數據表,dt_docDAY01,dt_docDAY02,dt_docDAY03等

每個DataTable包含一個帳號「帳號」,並存儲在列指的一天「DAY01」的平衡,「DAY02」等。

您能否告訴我如何更改代碼,以便包含所有表中的所有帳戶。

另外,我將如何合併在這段代碼中的所有數據表,所以我沒有運行這個相同的代碼31次。

' string id =「Account#」;

   var tableJoinedDAY02 = dt_docDAY01_GROUPED.Clone(); // create columns from table1 

       // add columns from table2 except id 
       foreach (DataColumn column in dt_docDAY02_GROUPED.Columns) 
       { 
        if (column.ColumnName != id) 
         tableJoinedDAY02.Columns.Add(column.ColumnName, column.DataType); 
       } 

       tableJoinedDAY02.BeginLoadData(); 

       foreach (DataRow row1 in dt_docDAY01_GROUPED.Rows) 
       { 
        foreach (DataRow row2 in dt_docDAY02_GROUPED.Rows) 
        { 
         if (row1.Field<string>(id) == row2.Field<string>(id)) 
         { 
          var list = row1.ItemArray.ToList(); // items from table1 

          // add items from table2 except id 
          foreach (DataColumn column in dt_docDAY02_GROUPED.Columns) 
           if (column.ColumnName != id) 
            list.Add(row2[column]); 

          tableJoinedDAY02.Rows.Add(list.ToArray()); 
         } 
        } 
       } 

        tableJoinedDAY02.EndLoadData();` 

表1

 
Account# | Day01 
1234  |  11 
4567  |  22 
0909  |  33 

表2

 
Account# | Day02 
1234  |  12 
0909  |  34 
5578  |  99 
0065  |  34 

表3

 
Account# | Day03 
1234  |  13 
7777  |  44 

預期結果合併表

表1

 
Account# | Day01  | Day02  | Day03 
1234  |  11  |  12  |  13 
4567  |  22  |  0  |  0 
0909  |  33  |  34  |  0 
5578  |  0  |  99  |  0 
0065  |  0  |  34  |  0 
7777  |  0  |  0  |  44 
+0

@GerardoGrignoli感謝您的downvote,超級有用,而不是。 – Infost

+0

這個內連接示例如何幫助我加入超過2個表的事實? – Infost

+1

您可以將Table1與Table2連接到Table12中。然後將Table12和Table3連接到Table123中,依此類推。 –

回答

1

這就需要按以下方式處理,所有的表不能用魔法結合在一起,讓我們更小的樣本集:

  1. 表1(DT1) - 帳號| Day01
  2. Table2(dt2) - 帳戶#| Day02
  3. Table3(dt3) - 帳號# Day03
  4. Table4(dt4) - 賬戶# Day04
上述操作的
dt1.AsEnumerable() 
    .Join(dt2.AsEnumerable(), d1 => (int)d1["Account#"], d2 =>    
      (int)d2["Account#"], 
      (d1,d2) => new {Account = (int)d1["Account#"],Day01 = 
        d1["Day01"],Day02 = d2["Day02"]}) 
    .Join(dt3.AsEnumerable(), d12 => d12.Account, d3 => (int)d3["Account#"], 
     (d12,d3) => new {d12.Account,d12.Day01,d12.Day02,Day03=d3["Day03"]}) 
    .Join(dt4.AsEnumerable(), dAll => dAll.Account, d4 => 
      (int)d4["Account#"], 
      (dAll,d4) => new 
     {dAll.Account,dAll.Day01,dAll.Day02,dAll.Day03,Day04=d4["Day04"]}) 

結果將是IEnumerable<AnonymousType>,在截至目前的匿名類型由屬性Account,Day01,Day02,Day03,Day04的,同樣你可以添加多達Day31。同樣要注意後首先加入我們開始使用作爲最後Join語句的一部分產生的AnonymousType

這需要轉換成DataTable,這將是類似於張貼在下面的線程代碼的東西:

Convert IEnumerable to DataTable

還要檢查此作爲其轉化爲DataTable using IEnumerable of Anonymous type,使用的NuGet效用Fastmember

C# how to convert IEnumerable anonymous lists into data table

+0

您好先生,你能提供更多的信息,我如何獲得這個列表數據回到數據表? – Infost

+0

檢查此http://stackoverflow.com/a/8525024/1559611,它有一個很好的解決方案 –

4

@Infost,你正試圖做什麼在SQL語言是full outer join。搜索上SO指出,這個答案https://stackoverflow.com/a/16832096/97471,我已經適應了超過2個表:

DataTable table1 = new DataTable(); 
table1.Columns.Add("Account", typeof(int)); 
table1.Columns.Add("Day01", typeof(decimal)); 

table1.Rows.Add(1234, 11); 
table1.Rows.Add(4567, 22); 
table1.Rows.Add(0909, 33); 

DataTable table2 = new DataTable(); 
table2.Columns.Add("Account", typeof(int)); 
table2.Columns.Add("Day02", typeof(decimal)); 

table2.Rows.Add(1234, 12); 
table2.Rows.Add(0909, 34); 
table2.Rows.Add(5578, 99); 
table2.Rows.Add(0065, 34); 

DataTable table3 = new DataTable(); 
table3.Columns.Add("Account", typeof(int)); 
table3.Columns.Add("Day03", typeof(decimal)); 

table3.Rows.Add(1234, 13); 
table3.Rows.Add(7777, 44); 

您可以加入他們調用以下功能:

MVCE像這樣的開始

var table123 = FullOuterJoinDataTables(table1, table2, table3); 

下面是函數源:

DataTable FullOuterJoinDataTables(params DataTable[] datatables) // supports as many datatables as you need. 
{ 
    DataTable result = datatables.First().Clone(); 

    var commonColumns = result.Columns.OfType<DataColumn>(); 

    foreach (var dt in datatables.Skip(1)) 
    { 
     commonColumns = commonColumns.Intersect(dt.Columns.OfType<DataColumn>(), new DataColumnComparer()); 
    } 

    result.PrimaryKey = commonColumns.ToArray(); 

    foreach (var dt in datatables) 
    { 
     result.Merge(dt, false, MissingSchemaAction.AddWithKey); 
    } 

    return result; 
} 

/* also create this class */ 
public class DataColumnComparer : IEqualityComparer<DataColumn> 
{ 
    public bool Equals(DataColumn x, DataColumn y) { return x.Caption == y.Caption; } 

    public int GetHashCode(DataColumn obj) { return obj.Caption.GetHashCode(); } 

} 

輸出是

 
Account Day01 Day02 Day03 
1234 11  12  13 
4567 22 
909  33  34 
5578   99 
65    34 
7777     44 
+0

Gerardo,這看起來很完美,我不能正確編譯功能。 – Infost

+0

我在這一行上有意想不到的字符 var table123 = FullOuterJoinDataTables(table1,table2,table3);. 我在課堂上也有錯誤,但它已修復與您的編輯。 – Infost

+0

您使用的是什麼.net框架?什麼編譯錯誤在哪一行? –

相關問題