2016-08-18 17 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框架?什么编译错误在哪一行? –

相关问题