You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C#中合并DataTable重复行并更新指定列的实现需求

合并C# DataTable中的重复行并更新列

嘿,我来帮你搞定这个DataTable合并重复行的需求!根据你给出的示例数据,我猜你是想tidcodepNameLocal这几个标识列来合并重复条目,然后对qty求和,同时合理处理price列(毕竟你例子里有同标识但价格不同的情况)。下面是具体的实现方案:

核心思路

  1. 确定分组规则:把tidcodepNameLocal完全相同的行归为一组(这些就是我们要合并的重复行)
  2. 聚合列值:对每组的qty求和;针对price,推荐用加权平均(按数量占比计算,更符合业务逻辑),如果组内价格完全一致则直接取用该值
  3. 生成新表:基于原表结构创建新表,把聚合后的结果写入新表(避免修改原数据,方便后续回溯)

代码实现

// 1. 按标识列分组并聚合数据
var groupedRows = dtDetails.AsEnumerable()
    .GroupBy(row => new {
        Tid = row.Field<int>("tid"),
        Code = row.Field<int>("code"),
        PNameLocal = row.Field<string>("pNameLocal")
    })
    .Select(group => {
        // 对qty求和
        int totalQty = group.Sum(row => row.Field<int>("qty"));
        
        // 处理price列:优先判断是否所有价格一致
        var priceList = group.Select(row => row.Field<decimal>("price")).ToList();
        decimal finalPrice;
        
        if (priceList.Distinct().Count() == 1)
        {
            // 所有价格相同,直接取该值
            finalPrice = priceList.First();
        }
        else
        {
            // 价格不一致,按数量加权平均(更贴合实际业务)
            decimal totalAmount = group.Sum(row => row.Field<decimal>("price") * row.Field<int>("qty"));
            finalPrice = Math.Round(totalAmount / totalQty, 2);
            // 可选:如果需要标记差异,可新增备注列,比如 mergedRow["note"] = "存在多档价格";
        }
        
        // 创建符合原表结构的新行
        DataRow mergedRow = dtDetails.NewRow();
        mergedRow["id"] = group.First().Field<int>("id"); // 取分组内第一个id,也可自定义生成规则
        mergedRow["tid"] = group.Key.Tid;
        mergedRow["code"] = group.Key.Code;
        mergedRow["pNameLocal"] = group.Key.PNameLocal;
        mergedRow["qty"] = totalQty;
        mergedRow["price"] = finalPrice;
        
        return mergedRow;
    });

// 2. 创建合并后的DataTable
DataTable mergedDt = dtDetails.Clone(); // 复制原表的结构(含列定义)
foreach (var row in groupedRows)
{
    mergedDt.Rows.Add(row);
}

// mergedDt就是最终的合并结果啦!

补充:如果只合并完全相同的行(所有列值一致)

如果你想要的是仅合并所有列完全相同的行(比如你的示例中行2和行3),可以用下面的简化代码:

var groupedRows = dtDetails.AsEnumerable()
    .GroupBy(row => row.ItemArray) // 用所有列的值作为分组依据
    .Select(group => {
        DataRow mergedRow = group.First();
        // 对完全相同的行,qty求和
        mergedRow["qty"] = group.Sum(r => r.Field<int>("qty"));
        return mergedRow;
    });

DataTable mergedDt = dtDetails.Clone();
foreach (var row in groupedRows)
{
    mergedDt.ImportRow(row);
}

结果说明

用第一种方案处理你的示例数据,最终合并后的结果会是:

idtidcodepNameLocalqtyprice
1101101some_local_name220.36
2102202some_local_name514.24

(注:14.24是按加权平均计算的结果:(15.3×1 + 15.3×1 + 10×1 + 15.3×2) ÷ 5 = 71.2 ÷ 5 = 14.24)

内容的提问来源于stack exchange,提问作者Abdul

火山引擎 最新活动