如何使用LINQ对重复GradeGroupCode分组并合并汇总总费用
问题核心
你当前的LINQ逻辑在GroupBy之后直接取每个分组的第一条数据,完全没有触发聚合计算,自然无法实现同等级组的金额累加。要实现合并需求,需要在分组完成后,针对每个分组重新生成汇总后的AvgCostSummary对象,区分固有属性和需要累加的汇总属性分别处理。你之前写的Select(item => item.First())本质上是把每个分组的容器直接拍扁成单条原始记录,跳过了所有聚合步骤,相当于和没写GroupBy的区别只是把重复编码的记录只留一条,完全没计算累加值。
具体实现方案
字段属性拆分
首先明确AvgCostSummary中不同字段的处理逻辑:
- 分组固有属性:同个
GradeGroupCode下这些字段值完全一致,不需要累加,直接取组内任意一条的值即可,包括GradeGroupCode、Grade、PeriodBegin、PeriodEnd - 跨主体汇总属性:需要把所有下属子公司对应的值累加,包括
QtyRecNt、TotalCost、Discount - 衍生计算属性:像
AvgCostDl、AvgPricePerLb这类平均字段,不能直接累加也不能直接取第一条的值,必须用汇总后的总金额、总数量重新计算,否则会出现平均数值偏差 - 无需处理字段:
ConsNum不参与最终展示,不需要赋值
可直接复用的LINQ代码
return summaryResults // 按Trim后的等级组编码分组,避免首尾空格导致同值编码被拆分 .GroupBy(item => item.GradeGroupCode.Trim()) .Select(group => { // 取组内第一条记录的固有属性值(同组内这些值逻辑上完全一致) var baseItem = group.First(); // 计算组内需要累加的汇总值 var totalQty = group.Sum(x => x.QtyRecNt); var totalCost = group.Sum(x => x.TotalCost); var totalDiscount = group.Sum(x => x.Discount); return new AvgCostSummary { GradeGroupCode = group.Key, Grade = baseItem.Grade.Trim(), PeriodBegin = baseItem.PeriodBegin, PeriodEnd = baseItem.PeriodEnd, QtyRecNt = totalQty, TotalCost = totalCost, Discount = totalDiscount, // 基于汇总后的数值重新计算平均,覆盖除以零的边界问题 AvgCostDl = totalQty == 0 ? 0 : totalCost / totalQty, AvgPricePerLb = totalQty == 0 ? 0 : totalCost / totalQty, }; }) .ToList();
注意事项
- 不要直接修改组内
First()取出的原始对象的属性,一定要new一个全新的AvgCostSummary实例返回,避免修改原始集合的对象引发非预期的副作用 - 如果业务场景中存在脏数据(比如同个
GradeGroupCode对应的Grade、Period属性不一致),需要在分组逻辑里加校验,发现不一致时记录日志排查数据问题,不要直接静默取第一条的值 - 举例中提到的"Magneisum"拼写偏差的场景,属于数据本身的拼写错误,上述逻辑无法自动合并这类不同编码的记录,需要在数据录入环节做统一校验
内容的提问来源于stack exchange,提问作者Adam Schneider
相关产品推荐
相关产品推荐

