简体   繁体   English

LINQ:结合加入和分组依据

[英]LINQ: combining join and group by

I have a query that combines a join and a group, but I have a problem.我有一个结合了连接和组的查询,但我遇到了问题。 The query is like:查询是这样的:

 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. 
 };

As you see, it joins the Products table with the BaseProducts table, and groups on an id of the Product table.如您所见,它将Products表与BaseProducts表连接起来,并根据Product表的 id 分组。 But in the resulting ProductPriceMinMax , I also need a property of the BaseProducts table: bp.Name , but it doesn't know bp .但是在生成的ProductPriceMinMax ,我还需要BaseProducts表的一个属性: bp.Name ,但它不知道bp

Any idea what I'm doing wrong?知道我做错了什么吗?

Once you've done this一旦你完成了这件事

group p by p.SomeId into pg  

you no longer have access to the range variables used in the initial from .您不再可以访问初始from使用的范围变量。 That is, you can no longer talk about p or bp , you can only talk about pg .也就是说,你不能再谈论pbp ,你只能谈论pg

Now, pg is a group and so contains more than one product.现在, pg是一个,因此包含多个产品。 All the products in a given pg group have the same SomeId (since that's what you grouped by), but I don't know if that means they all have the same BaseProductId .给定pg组中的所有产品都具有相同的SomeId (因为这是您分组的内容),但我不知道这是否意味着它们都具有相同的BaseProductId

To get a base product name, you have to pick a particular product in the pg group (As you are doing with SomeId and CountryCode ), and then join to BaseProducts .为了得到一个基本产品的名称,你必须选择一个特定的产品pg组(如你有做SomeIdCountryCode ),然后加入到BaseProducts

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
 };

That said, this looks pretty unusual and I think you should step back and consider what you are actually trying to retrieve.也就是说,这看起来很不寻常,我认为您应该退后一步,考虑一下您实际尝试检索的内容。

We did it like this:我们是这样做的:

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
};

EDIT: we used the version of AakashM, because it has better performance编辑:我们使用了 AakashM 的版本,因为它具有更好的性能

I met the same problem as you.我遇到了和你一样的问题。

I push two tables result into t1 object and group t1 .我将两个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
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM