【问题标题】:Outer Joining two Data Tables on multiple criteria根据多个条件外部连接两个数据表
【发布时间】:2015-10-09 22:05:27
【问题描述】:

我正在尝试使用基于多个条件的 Linq 加入两个数据表。我能够使用这篇文章进行合并:Combining two tables into one。但是,该示例仅连接一个主键,我需要能够指定多个条件。

DataTable1(代码中的table1)

+-----------------------------------------------+
| CLIENT,USER_NAME,LAST_LOGIN_DT_TM,BIRTH_DT_TM |
+-----------------------------------------------+
| CLIENT1, USER1, 30-2014, 5-5-1980             |
| CLIENT1, USER2, 12-21-2014, 5-2-1990          |
| CLIENT2, USER3, 11-30-2014, 5-1-1950          |
| CLIENT2, USER4, 12-15-2014, 1-1-1900          |
+-----------------------------------------------+

DataTable 2(代码中的table2)

+-------------------------------+
| CLIENT,USER_NAME,TOTAL_ORDERS |
+-------------------------------+
| CLIENT1, USER1, 1500          |
| CLIENT2, USER2, 2500          |
+-------------------------------+

我希望输出如下所示:

+-------------------------------------------------------------+
| CLIENT,USER_NAME,LAST_LOGIN_DT_TM,BIRTH_DT_TM, TOTAL_ORDERS |
+-------------------------------------------------------------+
| CLIENT1, USER1, 1-30-2014, 5-5-1980, 1500                   |
| CLIENT1, USER2, 12-21-2014, 5-2-1990,                       |
| CLIENT2, USER2, 11-30-2014, 5-1-1950, 2500                  |
| CLIENT2, USER1, 12-15-2014, 1-1-1900,                       |
+-------------------------------------------------------------+

这是我目前所拥有的:

DataTable targetTable = table1.Clone();

var dt2Columns = table2.Columns
                       .OfType<DataColumn>()
                       .Select(dc => new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns = from dc in dt2Columns.AsEnumerable()
                      where targetTable.Columns.Contains(dc.ColumnName) == false
                      select dc;
                      targetTable.Columns.AddRange(dt2FinalColumns.ToArray());

//  This only matches on USER_NAME now, how do I add in CLIENT?
var rowData = from row1 in table1.AsEnumerable()
              join row2 in table2.AsEnumerable()
              on row1.Field<string>("USER_NAME") equals row2.Field<string>("USER_NAME")
              select row1; 
// This gives me the matched rows in rowData, but I'm not sure how to join it with original table1

【问题讨论】:

    标签: c# .net linq join


    【解决方案1】:

    Fiel你需要通过使用新的 {Field1, Field2} 来使用匿名类型加入

    IEnumerable<DataRow> rowData = from row1 in table1.AsEnumerable()
              join row2 in table2.AsEnumerable()
              on new { col1 = row1.Field<string>("USER_NAME"),  col2 = row1.Field<string>("SecondField") }  equals {col1 = row2.Field<string>("USER_NAME") , col2 = row2.Field<string>("SecondField") }
              select row1; 
    

    【讨论】:

    • 不会编译。这不是一个正确的匿名类型声明,因为编译器将无法为您推断属性名称。
    【解决方案2】:

    要加入多个列,您必须使用匿名类型:

    from row1 in table1.AsEnumerable()
    join row2 in table2.AsEnumerable() on
      new { userName = row1.Field<string>("USER_NAME"), client = row1.Field<string>("CLIENT") }
    equals
      new { userName = row2.Field<string>("USER_NAME"), client = row2.Field<string>("CLIENT") }
    select new {
        userName = row1.Field<string>("USER_NAME"),
        client = row1.Field<string>("CLIENT"),
        totalOrders = row2.Field<int>("TOTAL_ORDERS"),
        (...)
    }
    

    【讨论】:

    • 这会处理匹配并将两个匹配的行放入rowData。之后获得我想要的外连接输出的最佳方法是什么?
    • 您可以投影到不同的匿名类型。更新了我的答案。
    • 如果直到运行时我才知道每个 DataTable 中的所有列怎么办?在我的真实场景中,table1 大约有 55 列,table2 大约有 25 列。我只知道每个表都有“CLIENT”和“USER_NAME”列。
    • 是的,我犯了一个错误,我的代码无法编译。但是,即使您的代码无法编译,您也缺少“客户”的引号:)
    • @MarcinJuraszek 抱歉在我之前的评论中没有标记你。如果在运行时我不知道每个 DataTable 中的列,有什么想法吗?我想避免在我的代码中写出 50 多列。谢谢
    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    相关资源
    最近更新 更多