【发布时间】:2015-12-12 09:23:44
【问题描述】:
我正在尝试加入两个数据表,它们的行数相同,只有一列。 C# 中有什么奇特的方法可以做到这一点吗?结果,我需要包含两列的数据表,其中第一列的第一行紧挨第二列的第一行。
【问题讨论】:
-
你能告诉我们你到目前为止所做的尝试吗?
标签: c#
我正在尝试加入两个数据表,它们的行数相同,只有一列。 C# 中有什么奇特的方法可以做到这一点吗?结果,我需要包含两列的数据表,其中第一列的第一行紧挨第二列的第一行。
【问题讨论】:
标签: c#
这是执行此操作的一种方法,所以基本上它使用.Select 的重载,它提供迭代中当前位置的索引,以查找我们当前在@987654323 中查看的table2 中的相应行@。我们为每一行从每个表中生成一个包含两个项目的对象数组。然后我们可以使用LoadDataRow 将它们放入包含两列的目标表中。
// create a target table with 2 columns
DataTable destinationTable = new DataTable();
destinationTable.Columns.Add("Col1");
destinationTable.Columns.Add("Col2");
// select all the rows from the first table, combined with the corresponding value for that row in the second table
var rowsCombined = table1
.AsEnumerable()
.Select((row, rowNumber) => new object[] { row[0], table2.Rows[rowNumber][0] });
foreach (var data in rowsCombined)
destinationTable.LoadDataRow(data, true);
【讨论】:
来自 Tim Schmelter 在此链接上的 ANSWER....
public static DataTable MergeAll(this IList<DataTable> tables, String primaryKeyColumn)
{
if (!tables.Any())
throw new ArgumentException("Tables must not be empty", "tables");
if(primaryKeyColumn != null)
foreach(DataTable t in tables)
if(!t.Columns.Contains(primaryKeyColumn))
throw new ArgumentException("All tables must have the specified primarykey column " + primaryKeyColumn, "primaryKeyColumn");
if(tables.Count == 1)
return tables[0];
DataTable table = new DataTable("TblUnion");
table.BeginLoadData(); // Turns off notifications, index maintenance, and constraints while loading data
foreach (DataTable t in tables)
{
table.Merge(t); // same as table.Merge(t, false, MissingSchemaAction.Add);
}
table.EndLoadData();
if (primaryKeyColumn != null)
{
// since we might have no real primary keys defined, the rows now might have repeating fields
// so now we're going to "join" these rows ...
var pkGroups = table.AsEnumerable()
.GroupBy(r => r[primaryKeyColumn]);
var dupGroups = pkGroups.Where(g => g.Count() > 1);
foreach (var grpDup in dupGroups)
{
// use first row and modify it
DataRow firstRow = grpDup.First();
foreach (DataColumn c in table.Columns)
{
if (firstRow.IsNull(c))
{
DataRow firstNotNullRow = grpDup.Skip(1).FirstOrDefault(r => !r.IsNull(c));
if (firstNotNullRow != null)
firstRow[c] = firstNotNullRow[c];
}
}
// remove all but first row
var rowsToRemove = grpDup.Skip(1);
foreach(DataRow rowToRemove in rowsToRemove)
table.Rows.Remove(rowToRemove);
}
}
return table;
}
可以这样调用:
var tables = new[] { tblA, tblB, tblC };
DataTable TblUnion = tables.MergeAll("c1");
一些样本数据:
var tblA = new DataTable();
tblA.Columns.Add("c1", typeof(int));
tblA.Columns.Add("c2", typeof(int));
tblA.Columns.Add("c3", typeof(string));
tblA.Columns.Add("c4", typeof(char));
var tblB = new DataTable();
tblB.Columns.Add("c1", typeof(int));
tblB.Columns.Add("c5", typeof(int));
tblB.Columns.Add("c6", typeof(string));
tblB.Columns.Add("c7", typeof(char));
var tblC = new DataTable();
tblC.Columns.Add("c1", typeof(int));
tblC.Columns.Add("c8", typeof(int));
tblC.Columns.Add("c9", typeof(string));
tblC.Columns.Add("c10", typeof(char));
tblA.Rows.Add(1, 8500, "abc", 'A');
tblA.Rows.Add(2, 950, "cde", 'B');
tblA.Rows.Add(3, 150, "efg", 'C');
tblA.Rows.Add(4, 850, "ghi", 'D');
tblA.Rows.Add(5, 50, "ijk", 'E');
tblB.Rows.Add(1, 7500, "klm", 'F');
tblB.Rows.Add(2, 900, "mno", 'G');
tblB.Rows.Add(3, 150, "opq", 'H');
tblB.Rows.Add(4, 850, "qrs", 'I');
tblB.Rows.Add(5, 50, "stu", 'J');
tblC.Rows.Add(1, 7500, "uvw", 'K');
tblC.Rows.Add(2, 900, "wxy", 'L');
tblC.Rows.Add(3, 150, "yza", 'M');
tblC.Rows.Add(4, 850, "ABC", 'N');
tblC.Rows.Add(5, 50, "CDE", 'O');
mergeAll 调用后:
希望这会有所帮助...
【讨论】: