将n个数据表组合成单个数据表

所有这些都有一些问题,但我似乎无法提取足够的信息来解决我的问题。 我提取未知数量的表到SQL Server的“Tab1”,“Tab2”,“Tab3”,…,“TabN”。 这些表中的列是不同的,但行定义是相同的。 我需要将所有的数据从服务器中提取到N个DataTable ,然后将它们组合成一个DataTable 。 我现在做的是

 int nTmpVolTabIdx = 1; strSqlTmp = String.Empty; using (DataTable dataTableALL = new DataTable()) { while (true) { string strTmpVolName = String.Format("Tab{0}", nTmpVolTabIdx); strSqlTmp = String.Format("SELECT * FROM [{0}];", strTmpVolName); // Pull the data from 'VolX' into a local DataTable. using (DataTable dataTable = UtilsDB.DTFromDB(conn, strTmpVolName, strSqlTmp, false)) { if (dataTable == null) break; else dataTableALL.Merge(dataTable); } nTmpVolTabIdx++; } ... } 

这合并了DataTable但它们是未alignment的(将空白单元填充到附加的数据集上)。 我可以通过循环追加新的DataTable的列; 但有没有更容易/更好的方式来做到这一点(也许使用LINQ)?

谢谢你的时间。

编辑。 提供示例数据集。

我需要的是

完整的数据表

个人表是

标签

在第一次合并操作后,我有以下几点

合并后

再次感谢。

该表在Merge后重复主键,因为没有定义主键。 所以要么指定PK或尝试这个我从头开始写的方法(所以它没有真正testing)

 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 DataTable.Merge MergeAll

在这里输入图像描述

经过一些修改以joinMergeAll的行:

在这里输入图像描述


更新

由于这个问题出现在其中一个注释中,如果两个表之间的唯一关系是表中DataRow的索引,并且您希望根据索引合并两个表:

 public static DataTable MergeTablesByIndex(DataTable t1, DataTable t2) { if (t1 == null || t2 == null) throw new ArgumentNullException("t1 or t2", "Both tables must not be null"); DataTable t3 = t1.Clone(); // first add columns from table1 foreach (DataColumn col in t2.Columns) { string newColumnName = col.ColumnName; int colNum = 1; while (t3.Columns.Contains(newColumnName)) { newColumnName = string.Format("{0}_{1}", col.ColumnName, ++colNum); } t3.Columns.Add(newColumnName, col.DataType); } var mergedRows = t1.AsEnumerable().Zip(t2.AsEnumerable(), (r1, r2) => r1.ItemArray.Concat(r2.ItemArray).ToArray()); foreach (object[] rowFields in mergedRows) t3.Rows.Add(rowFields); return t3; } 

样品:

 var dt1 = new DataTable(); dt1.Columns.Add("ID", typeof(int)); dt1.Columns.Add("Name", typeof(string)); dt1.Rows.Add(1, "Jon"); var dt2 = new DataTable(); dt2.Columns.Add("Country", typeof(string)); dt2.Rows.Add("US"); var dtMerged = MergeTablesByIndex(dt1, dt2); 

结果表包含三列IDNameCountry和单行: 1 Jon US