LINQ,加入,分组和聚合

时间:2011-03-10 00:01:13

标签: c# .net linq

使用Join或GroupJoin,是否有任何方法可以为父表和子表中的字段生成聚合值。给定一个Orders表和一个OrderDetails表,使用下面的两个步骤,我可以从Orders获得一个聚合(MAX),从OrderDetails获得一个聚合(SUM)。

第1步:

var query = from o in orders
                    join d in details on o.OrderId equals d.OrderId
                    select new
                    {
                        order = o.OrderId,
                        maximum = o.UserId,
                        quantity = d.Quantity
                    };

第2步:

var result = (from q in query
                      group q by q.order into g
                      select new 
                      {
                          OrderId = g.Key,
                          MaxUnits = g.Max(q => q.maximum),
                          Available = (g.Max(q => q.maximum) - g.Sum(q => q.quantity))
                      });

但是,当我尝试将它们组合在一起时:

var finalresult   = orders  
                    .GroupJoin(  details,  
                    o => o.OrderId,  
                    d => d.OrderDetailId,  
                    (o, grp) => new {
                        OrderId = o.OrderId,
                        MaxUnits = grp.Max(o => o.maximum),
                        Available = (grp.Max(o => o.maximum) - grp.Sum(d => d.Quantity))
                    });

..值'o'超出了分组集'grp'的范围。因此grp.Max(o => o.maximum)导致错误。似乎只有子表(OrderDetail)的聚合值可用。

所以有人知道是否可以在单个查询中从子表和父表中获取聚合?

1 个答案:

答案 0 :(得分:1)

result 单个查询。 LINQ和延迟执行的优点在于步骤1中没有发生实际计算,只定义了查询。然后,步骤2构建该查询的ontop以创建另一个单个查询。当您执行result时,查询将作为单个块执行。

我建议将较大的查询拆分为较小的易于理解的部分,如前两个示例中所示。为查询使用好名称可以使它们更容易阅读。例如,我可能会命名查询orderQuantities。 from q in query并未传达太多意义,但from oq in orderQuantities让我知道查询的数据类型。

如果你真的认为你需要它们:

var query = orders.Join(details, o => o.OrderId, d => d.OrderId, 
    (o, d) => new {
        order = o.OrderId, 
        maximum = o.UserId, 
        quantity = d.Quantity
    }).GroupBy(oq => oq.order)
    .Select(g => new {
        OrderId = g.Key, 
        MaxUnits = g.Max(q => q.maximum), 
        Available = (g.Max(q => q.maximum) - g.Sum(q => q.quantity))
    }); 

现在这很难看......