C# DataTable 内连接与动态列

Posted

技术标签:

【中文标题】C# DataTable 内连接与动态列【英文标题】:C# DataTable Inner join with dynamic columns 【发布时间】:2012-05-17 04:00:19 【问题描述】:

我正在尝试以与此问题类似的方式将两个数据表连接在一起:

Inner join of DataTables in C#

我试图让输出成为一个“组合”表,其中包含两个原始表中的列。它们都有一个共同的日期戳列。

给出的答案对于具有固定列的 DataTables 来说很好,但是如果它们是动态创建的,并且可以有任意数量的列,我该如何加入它们呢?

例如

T1 (datestamp, t1Column1, t1Column2, t1ColumnN...)
T2 (datestamp, t2Column1, t2Column2, t2ColumnN...)

我想加入创建以下内容:

J1 (datestamp, t1Column1, t1Column2, t1ColumnN, ..., t2Column1, t2Column2, t2ColumnN...)

这可能吗?

【问题讨论】:

你能举个例子说明你想要的结果吗? 我不认为 Linq 是一个选项,因为您需要知道您尝试投影到的列名称。 好的,但可以让我这样做,请你举一个例子,有两个数据表和你想要的结果。 【参考方案1】:

我找到了一个不依赖于循环遍历列的解决方案。

它使用“合并”方法,我之前认为这两个表需要相同的结构而忽略了该方法。

首先你需要在两个数据表上创建一个主键:

// 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)

【讨论】:

【参考方案2】:

我认为您可以调整链接问题中的答案以使用index of the column,而不是列名。或者您可以只循环遍历每一行中的项目,如下所示:

foreach(DataRow row in table.Rows)

    foreach(DataColumn column in table.Columns)
    
        object value = row[column]; // add this to your combined table
    

【讨论】:

谢谢 - 我希望避免循环遍历所有列,因为我已经有一些嵌套循环来设置原始表。如果表中的数据有很多不同的日期/键,这可能会变得相当复杂。【参考方案3】:

在厌倦了所有这些不能可靠地模拟 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"));

【讨论】:

干得好。有没有办法修改它以便能够在多个“加入”条件之间指定 AND 或 OR 运算符?

以上是关于C# DataTable 内连接与动态列的主要内容,如果未能解决你的问题,请参考以下文章

c# 如何将多个单行多列的datatable合并成一个单行多列的datatable,表中内容是string..

将列内包含 JSON 数组的行扩展为多行

C#基础之使用DataSet与Datatable更新数据库的三种实现方法

复合条件连接,内连接,左右连接,自然连接,等值连接

MySQL 查询

C# 怎样才能实现客户端通过服务器端连接数据库服务器???