LINQ:结合加入和分组依据

Posted

技术标签:

【中文标题】LINQ:结合加入和分组依据【英文标题】:LINQ: combining join and group by 【发布时间】:2012-02-28 17:06:39 【问题描述】:

我有一个结合了联接和组的查询,但我遇到了问题。查询是这样的:

 var result = from p in Products                         
 join bp in BaseProducts on p.BaseProductId equals bp.Id                    
 group p by p.SomeId into pg                         
 select new ProductPriceMinMax  
       SomeId = pg.FirstOrDefault().SomeId, 
       CountryCode = pg.FirstOrDefault().CountryCode, 
       MinPrice = pg.Min(m => m.Price), 
       MaxPrice = pg.Max(m => m.Price),
       BaseProductName = bp.Name  <------ can't use bp. 
 ;

如您所见,它将Products 表与BaseProducts 表连接起来,并在Product 表的ID 上进行分组。但是在生成的ProductPriceMinMax中,我还需要BaseProducts表的一个属性:bp.Name,但是它不知道bp

知道我做错了什么吗?

【问题讨论】:

【参考方案1】:

完成此操作后

group p by p.SomeId into pg  

您不再有权访问初始 from 中使用的范围变量。即不能再谈pbp,只能谈pg

现在,pg 是一个,因此包含多个产品。给定pg 组中的所有产品都具有相同的SomeId(因为这是您的分组依据),但我不知道这是否意味着它们都具有相同的BaseProductId

要获得基本产品名称,您必须在pg 组中选择一个特定产品(就像您对SomeIdCountryCode 所做的那样),然后然后加入@ 987654334@。

var result = from p in Products                         
 group p by p.SomeId into pg                         
 // join *after* group
 join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id         
 select new ProductPriceMinMax  
       SomeId = pg.FirstOrDefault().SomeId, 
       CountryCode = pg.FirstOrDefault().CountryCode, 
       MinPrice = pg.Min(m => m.Price), 
       MaxPrice = pg.Max(m => m.Price),
       BaseProductName = bp.Name  // now there is a 'bp' in scope
 ;

也就是说,这看起来很不寻常,我认为您应该退后一步,考虑一下您实际上要检索的内容。

【讨论】:

这比我们的解决方案更好:) 谢谢。 @AakashM 谢谢。但我正在获取 groupVariable.FirstOrDefault().column_name 的问题。当我要访问 IQueryable 变量 Result 时发生错误,标题为 “entitycommandexecutionexception 未被用户代码处理” 正文 “执行命令定义时发生错误。有关详细信息,请参阅内部异常。” 我不明白发生了什么。 @MuhammadAshikuzzaman 听起来你需要Ask a new question。请务必包含所有详细信息! FirstOrDefault() 总是返回空值。我让它与pg.Key 一起工作,这实际上更有意义。我不明白FirstOrDefault 将如何返回任何对象,而我的分组依据是someId @SZT 一旦你完成了group,你最终得到的东西(pg 这里)就是IGrouping。当您使用任何在IGrouping 上执行枚举类型的方法时,您正在迭代的是该组的成员。所以pg.FirstOrDefault() 是特定SomeId 组中Products 中的第一个(按任意顺序)。【参考方案2】:

我们是这样做的:

from p in Products                         
join bp in BaseProducts on p.BaseProductId equals bp.Id                    
where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate                         
group new  p, bp  by new  p.SomeId  into pg    
let firstproductgroup = pg.FirstOrDefault()
let product = firstproductgroup.p
let baseproduct = firstproductgroup.bp
let minprice = pg.Min(m => m.p.Price)
let maxprice = pg.Max(m => m.p.Price)
select new ProductPriceMinMax

SomeId = product.SomeId,
BaseProductName = baseproduct.Name,
CountryCode = product.CountryCode,
MinPrice = minprice, 
MaxPrice = maxprice
;

编辑:我们使用了 AakashM 的版本,因为它有更好的性能

【讨论】:

【参考方案3】:

我遇到了和你一样的问题。

我将两个tables result 推入t1 对象和组t1

 from p in Products                         
  join bp in BaseProducts on p.BaseProductId equals bp.Id
  select new 
   p,
   bp
   into t1
 group t1 by t1.p.SomeId into g
 select new ProductPriceMinMax  
  SomeId = g.FirstOrDefault().p.SomeId, 
  CountryCode = g.FirstOrDefault().p.CountryCode, 
  MinPrice = g.Min(m => m.bp.Price), 
  MaxPrice = g.Max(m => m.bp.Price),
  BaseProductName = g.FirstOrDefault().bp.Name
;

【讨论】:

以上是关于LINQ:结合加入和分组依据的主要内容,如果未能解决你的问题,请参考以下文章

具有动态分组依据的 LINQ

实体框架 LINQ - 具有分组依据的子查询

LINQ C# 中的条件计数分组依据

LINQ TO DataSet:数据表上的多个分组依据

加入和分组依据 - 选择列表中的列无效

EF Core 3.1 (LINQ) - 如何在多列上左加入和分组