LINQ: combining join and group by

前端 未结 3 820
无人共我
无人共我 2020-11-27 04:55

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 i         


        
相关标签:
3条回答
  • 2020-11-27 05:07

    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

    0 讨论(0)
  • 2020-11-27 05:12

    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. That is, you can no longer talk about p or bp, you can only talk about pg.

    Now, pg is a group and so contains more than one product. 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.

    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.

    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.

    0 讨论(0)
  • 2020-11-27 05:22

    I met the same problem as you.

    I push two tables result into t1 object and group 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
    };
    
    0 讨论(0)
提交回复
热议问题