DataTables在C#中的内部连接
让T1和T2是以下字段的数据表
T1(CustID, ColX, ColY) T2(CustID, ColZ)
我需要联合表
TJ (CustID, ColX, ColY, ColZ)
如何以简单的方式在C#代码中完成这项工作? 谢谢。
如果您可以使用LINQ,请看下面的例子。 它创build两个带有整数列的DataTables,用一些logging填充它们,使用LINQ查询将它们连接起来并输出到控制台。
DataTable dt1 = new DataTable(); dt1.Columns.Add("CustID", typeof(int)); dt1.Columns.Add("ColX", typeof(int)); dt1.Columns.Add("ColY", typeof(int)); DataTable dt2 = new DataTable(); dt2.Columns.Add("CustID", typeof(int)); dt2.Columns.Add("ColZ", typeof(int)); for (int i = 1; i <= 5; i++) { DataRow row = dt1.NewRow(); row["CustID"] = i; row["ColX"] = 10 + i; row["ColY"] = 20 + i; dt1.Rows.Add(row); row = dt2.NewRow(); row["CustID"] = i; row["ColZ"] = 30 + i; dt2.Rows.Add(row); } var results = from table1 in dt1.AsEnumerable() join table2 in dt2.AsEnumerable() on (int)table1["CustID"] equals (int)table2["CustID"] select new { CustID = (int)table1["CustID"], ColX = (int)table1["ColX"], ColY = (int)table1["ColY"], ColZ = (int)table2["ColZ"] }; foreach (var item in results) { Console.WriteLine(String.Format("ID = {0}, ColX = {1}, ColY = {2}, ColZ = {3}", item.CustID, item.ColX, item.ColY, item.ColZ)); } Console.ReadLine(); // Output: // ID = 1, ColX = 11, ColY = 21, ColZ = 31 // ID = 2, ColX = 12, ColY = 22, ColZ = 32 // ID = 3, ColX = 13, ColY = 23, ColZ = 33 // ID = 4, ColX = 14, ColY = 24, ColZ = 34 // ID = 5, ColX = 15, ColY = 25, ColZ = 35
我想要一个函数来连接表,而不需要使用匿名typesselect器来定义列,但是很难find任何列。 我最终不得不自己做。 希望这将有助于任何未来的人谁search这个:
private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn) { DataTable result = new DataTable(); foreach (DataColumn col in t1.Columns) { if (result.Columns[col.ColumnName] == null) result.Columns.Add(col.ColumnName, col.DataType); } foreach (DataColumn col in t2.Columns) { if (result.Columns[col.ColumnName] == null) result.Columns.Add(col.ColumnName, col.DataType); } foreach (DataRow row1 in t1.Rows) { var joinRows = t2.AsEnumerable().Where(row2 => { foreach (var parameter in joinOn) { if (!parameter(row1, row2)) return false; } return true; }); foreach (DataRow fromRow in joinRows) { DataRow insertRow = result.NewRow(); foreach (DataColumn col1 in t1.Columns) { insertRow[col1.ColumnName] = row1[col1.ColumnName]; } foreach (DataColumn col2 in t2.Columns) { insertRow[col2.ColumnName] = fromRow[col2.ColumnName]; } result.Rows.Add(insertRow); } } return result; }
你可以如何使用这个例子:
var test = JoinDataTables(transactionInfo, transactionItems, (row1, row2) => row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID"));
一个警告:这当然不是最优化的,所以在排列超过20k时要留意。 如果你知道一张桌子比另一张桌子大,那么先把小一个放大一个,再放大一个。
这是我的代码。 不完美,但工作良好。 我希望它有助于某人:
static System.Data.DataTable DtTbl (System.Data.DataTable[] dtToJoin) { System.Data.DataTable dtJoined = new System.Data.DataTable(); foreach (System.Data.DataColumn dc in dtToJoin[0].Columns) dtJoined.Columns.Add(dc.ColumnName); foreach (System.Data.DataTable dt in dtToJoin) foreach (System.Data.DataRow dr1 in dt.Rows) { System.Data.DataRow dr = dtJoined.NewRow(); foreach (System.Data.DataColumn dc in dtToJoin[0].Columns) dr[dc.ColumnName] = dr1[dc.ColumnName]; dtJoined.Rows.Add(dr); } return dtJoined; }
这个函数将会连接两个带有已知连接字段的表,但是这样做不能允许两个字段在连接字段之外的两个表上都有相同的名字,一个简单的修改就是用一个计数器保存一个字典,并且把数字添加到同一个名字filds。
public static DataTable JoinDataTable(DataTable dataTable1, DataTable dataTable2, string joinField) { var dt = new DataTable(); var joinTable = from t1 in dataTable1.AsEnumerable() join t2 in dataTable2.AsEnumerable() on t1[joinField] equals t2[joinField] select new { t1, t2 }; foreach (DataColumn col in dataTable1.Columns) dt.Columns.Add(col.ColumnName, typeof(string)); dt.Columns.Remove(joinField); foreach (DataColumn col in dataTable2.Columns) dt.Columns.Add(col.ColumnName, typeof(string)); foreach (var row in joinTable) { var newRow = dt.NewRow(); newRow.ItemArray = row.t1.ItemArray.Union(row.t2.ItemArray).ToArray(); dt.Rows.Add(newRow); } return dt; }