左外部联接后,Linq查询返回重复值

时间:2020-10-05 15:27:38

标签: c# linq

我的table1和table2都有唯一的记录,我需要离开外部联接以从table2获取DESCR。

表1:

ID
SUBJECT
CATALOG_NBR
...

表2:

SUBJECT
CATALOG_NBR
DESCR
...

但是,在离开外部联接之后,我得到了双记录。我尝试了groupby,但仍返回重复项。以下是我的查询:

IQueryable<joinedTable> qry = (from a in db.table1
    join b in db.table2 on 
        new { SUBJECT=a.SUBJECT, CATALOG_NBR=a.CATALOG_NBR } equals
        new { SUBJECT = b.SUBJECT, CATALOG_NBR = b.CATALOG_NBR } 
    into ab from x  in ab.DefaultIfEmpty()
    select new joinedTable()
    {
        ID=a.ID,
        SUBJECT=a.SUBJECT,
        CATALOG_NBR=a.CATALOG_NBR,
        DESCR=x.DESCR
    }
    .GroupBy(a=>a.ID)
    .Select(a=>a.FirstOrDefault())
    .AsQueryable();

查询中出了什么问题?谢谢。

1 个答案:

答案 0 :(得分:0)

因此,表1和表2的行具有一个主题和一个CatalogNr。并且您想要“表1的行,每个表具有零行或更多的表2行,这些行具有相同的Subject和CatalogNr值”

每当您想要零个或多个子项目的项目(例如,带有订单的客户,带有学生的学校,带有Table2Rows的Table1Rows)时,请考虑使用Queryable.GroupJoin的重载之一。

var result = dbContext.Table1Rows.GroupJoin(dbContext.Table2Rows,

    table1Row => new
    {
        Subject=table1Row.SUBJECT,
        CatalogNr=table1Row.CATALOG_NBR
    },
    table2Row => new
    {
        Subject=table2Row.SUBJECT,
        CatalogNr=table2Row.CATALOG_NBR
    },

    // parameter ResultSelector: take each row of Table1 and the zero or more matching
    // matching rows of Table2 to make one new:
    (table1Row, table2Rows) =>  new
    {
        Id = table1Row.Id,
        Subject = table1Row.SUBJECT,
        CatalogNr = table1Row.CATALOG_NBR,
        
        Table2Descriptions = table2Rows.Select(table2Row => table2Row.DESCR).ToList(),
    });

换句话说:

  • 在Table1的每一行中,创建一个新对象,其中包含该行的Subject和CatalogNr。
  • 在Table2的每一行中,创建一个新对象,其中包含该行的Subject和CatalogNr。
  • 对于表1中的每一行,以及表2中所有零个或更多匹配行,创建一个新对象,其中包含表1中该行的多个属性,以及一个属性Descriptions,该属性为匹配的table2行的所有description值的列表

与重复组合[客户1,订单1] [客户1,订单2] [客户2,订单3]等相比,“拥有订单的客户”感觉更自然。GroupJoin的另一个优点是每个客户的数据客户仅转移一次。

一个主要区别:通过左外部联接,您将不会获得没有订单的客户。有了GroupJoin,即使没有订单,您也将拥有每个客户。如果您不想这样做,请在以下位置添加一个简单的位置:

// keep only the table1 items that have at least one matching table2 item
.Where(groupJoinResult => groupJoinResult.Descriptions.Any())

如果您确实想要一个扁平的左外部联接,请使用SelectMany。我个人认为没有适当的理由。