[英]How to do a Full Outer Join of 2 or more Datatables in C# with a common column
我需要將C#上的數據表合並/聯接到一個公共列。
我知道有人問過許多關於同一主題的例子和問題。 我還沒有找到任何答案。
下面是我正在使用的代碼。
該代碼僅基於datatable上的數據允許一個公共列。 我需要一個公共列,但它需要考慮可以在另一個數據表中使用任何其他“ Account#”並將其添加到公共列中。
此外,該代碼僅允許合並2個數據表。 我需要合並31個數據表,每個月的每一天要合並1個數據表。
我每個月的每一天都有一個數據表,分別為dt_docDAY01,dt_docDAY02,dt_docDAY03等。
每個數據表都包含一個帳號“ Account#”和一個余額,該余額存儲在引用“ 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
@Infost,您正在嘗試執行SQL語言中的full outer join
聯接。 在SO上進行搜索時,指向了這個答案https://stackoverflow.com/a/16832096/97471 ,我已將其用於2個以上的表:
從這樣的MVCE開始:
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);
您可以通過以下功能加入他們:
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
這需要按以下方式處理,所有表不能通過魔術連接在一起,讓我們采用較小的樣本集:
- 表1(dt1)-帳戶編號| 第一天
- 表2(dt2)-帳戶編號| 第二天
- 表3(dt3)-帳戶編號| 第三天
- 表4(dt4)-帳戶編號| 第04天
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
,這類似於以下線程中發布的代碼:
還要檢查它是否可以使用Nuget實用程序Fastmember
使用DataTable using IEnumerable of Anonymous type
轉換為DataTable using IEnumerable of Anonymous type
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.