C# 数据表与动态列的内部联接
本文关键字:内部 数据表 动态 | 更新日期: 2023-09-27 18:33:36
我正在尝试以与此问题类似的方式将两个数据表连接在一起:
C# 中数据表的内部联接
我试图让输出是一个"组合"表,其中包含来自两个原始表的列。它们都有一个共同的日期戳列。
给出的答案适用于具有固定列的数据表,但是如果它们是动态创建的,并且可以具有任意数量的列,我该如何连接它们呢?
例如
T1 (datestamp, t1Column1, t1Column2, t1ColumnN...)
T2 (datestamp, t2Column1, t2Column2, t2ColumnN...)
我想加入以创建以下内容:
J1 (datestamp, t1Column1, t1Column2, t1ColumnN, ..., t2Column1, t2Column2, t2ColumnN...)
这可能吗?
我找到了一个不依赖于循环
列的解决方案。它使用"合并"方法,我之前已经忽略了该方法,因为我认为两个表需要相同的结构。
首先,您需要在两个数据表上创建一个主键:
// set primary key
T1.PrimaryKey = new DataColumn[] { T1.Columns["DateStamp"] };
T2.PrimaryKey = new DataColumn[] { T2.Columns["DateStamp"] };
然后将这两个表添加到数据集中,以便可以添加关系:
// add both data-tables to data-set
DataSet dsContainer = new DataSet();
dsContainer.Tables.Add(T1);
dsContainer.Tables.Add(T2);
接下来添加数据集中两个键列之间的关系:
// add a relationship between the two timestamp columns
DataRelation relDateStamp = new DataRelation("Date", new DataColumn[] { T1.Columns["DateStamp"] }, new DataColumn[] { T2.Columns["DateStamp"] });
dsContainer.Relations.Add(relDateStamp);
最后,您现在可以将第一个数据表复制到新的"组合"版本中,然后合并第二个:
// populate combined data
DataTable dtCombined = new DataTable();
dtCombined = T1.Copy();
dtCombined.Merge(T2, false, MissingSchemaAction.Add);
注意:Merge 方法要求第二个参数为 false,否则它会复制结构而不是第二个表的数据。
然后,这将合并下表:
T1 (2012-05-09, 111, 222)
T2 (2012-05-09, 333, 444, 555)
转换为基于主键的组合版本:
J1 (2012-05-09, 111, 222, 333, 444, 555)
我认为您可以调整链接问题中的答案以使用列的索引,而不是列名。或者,您可以循环遍历每行中的项目,如下所示:
foreach(DataRow row in table.Rows)
{
foreach(DataColumn column in table.Columns)
{
object value = row[column]; // add this to your combined table
}
}
在厌倦了看到所有这些不能可靠地模拟SQL的内部连接函数之后,我决定在这里制作自己的函数:
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"));