LINQ、连接、分组和聚合

3
使用Join或GroupJoin,是否有办法为父表和子表中的字段生成聚合值。给定一个Orders表和一个OrderDetails表,使用以下2个步骤,我可以从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
                    };

步骤二:

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

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

那么,有人知道是否可能在单个查询中从子表和父表中获取聚合吗?


你不能使用 let 关键字将它们组合起来吗? - Phil C
1个回答

1

result 一个单个查询。LINQ和延迟执行的美妙之处在于第一步没有实际计算,只定义了一个查询。然后,第二步在该查询的基础上创建另一个单个查询。当您执行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))
    }); 

现在这太丑了...


他们说美在观者的眼中,虽然我不认为你的回答很丑陋,但我会遵循你的建议出于你所述的原因将事物分开。作为一个老SQL程序员,我倾向于忘记延迟执行并尝试尽可能地合并。我相信你的答案真正的价值就在于这一点。LINQ有很高的概率可以比我更好地合并和优化。感谢你的时间。 - user646306

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接