使用C# LINQ对DataTable按SO和DATE去重并求和CTN、WT、CBM
没问题,我来帮你搞定这个需求!下面是针对你的DataTable分组求和需求的完整解决方案:
解决方案:C# LINQ按SO+DATE分组并求和对应字段
你的需求核心是按SO和DATE两个字段共同分组(实现去重效果),然后对每组内的CTN、WT、CBM分别计算总和。我们可以用LINQ的GroupBy结合Sum来实现,同时要注意DataTable字段的类型转换。
完整代码示例
// 假设你的源DataTable名为sourceDt var groupedResult = sourceDt.AsEnumerable() // 按SO和DATE组合字段分组 .GroupBy(row => new { SO = row.Field<string>("SO"), Date = row.Field<DateTime>("DATE") }) // 对每组求和并投影到新对象 .Select(group => new { SO = group.Key.SO, Date = group.Key.Date, TotalCTN = group.Sum(row => row.Field<int>("CTN")), TotalWT = group.Sum(row => row.Field<decimal>("WT")), TotalCBM = group.Sum(row => row.Field<decimal>("CBM")) }) .ToList();
代码细节解释
- 分组逻辑:用匿名类型把
SO和DATE作为联合分组键,确保只有这两个字段完全匹配的行才会被归为一组,实现你要的"去重"效果。 - 类型转换:用
Field<T>()方法把DataRow里的object类型值转换为对应强类型(字符串、日期、整数、小数),避免隐式转换的错误。 - 求和计算:针对每组内的CTN(整数类型)、WT/CBM(小数类型,适合处理精度要求高的数值)分别调用
Sum()计算总和。
可选:将结果转回DataTable格式
如果需要最终输出仍是DataTable,可以添加这段代码:
// 创建结果DataTable并定义列 DataTable resultDt = new DataTable(); resultDt.Columns.Add("SO", typeof(string)); resultDt.Columns.Add("DATE", typeof(DateTime)); resultDt.Columns.Add("TotalCTN", typeof(int)); resultDt.Columns.Add("TotalWT", typeof(decimal)); resultDt.Columns.Add("TotalCBM", typeof(decimal)); // 填充结果行 foreach (var item in groupedResult) { resultDt.Rows.Add(item.SO, item.Date, item.TotalCTN, item.TotalWT, item.TotalCBM); }
测试你的示例数据
用你提供的测试数据运行代码后,会得到如下结果:
| SO | DATE | TotalCTN | TotalWT | TotalCBM |
|---|---|---|---|---|
| CGP3941410 | 28-Mar-18 | 3 | 26.89 | 0.21 |
| CGP3941411 | 28-Mar-18 | 4 | 35.87 | 0.28 |
完全符合你"按SO和DATE去重+求和对应字段"的需求。
内容的提问来源于stack exchange,提问作者Tasneem Iram




