You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于非主键ROBAID合并存在重复值的两个DataTable?

处理ROBAID重复时的DataTable合并方案

原来的Merge方法之所以失效,核心问题在于它依赖主键进行匹配更新——当dt2的ROBAID出现重复值时,你甚至没法再把它设为主键(主键要求唯一性),就算跳过主键设置,Merge也会把同ROBAID的行当成对同一记录的更新,而不是保留所有匹配行。针对你的需求,我提供两种可靠的实现方式:

方法一:手动遍历构建合并表

这种方式直观易控,适合需要自定义逻辑的场景:

// 1. 创建结果表,复制dt1的结构并添加需要的列
DataTable mergedTable = dt1.Clone();
mergedTable.Columns.Add("STANJE", dt2.Columns["STANJE"].DataType);
mergedTable.Columns.Add("KOLICINA", dt2.Columns["KOLICINA"].DataType);

// 2. 遍历dt1的每一行
foreach (DataRow row1 in dt1.Rows)
{
    // 3. 筛选dt2中所有ROBAID匹配的行
    string filter = $"ROBAID = {row1["ROBAID"]}";
    // 如果ROBAID是字符串类型,要改成:filter = $"ROBAID = '{row1["ROBAID"]}'";
    DataRow[] matchingRows = dt2.Select(filter);

    if (matchingRows.Length > 0)
    {
        // 4. 为每个匹配行创建合并后的新行
        foreach (DataRow row2 in matchingRows)
        {
            DataRow newRow = mergedTable.NewRow();
            // 复制dt1的所有列数据
            foreach (DataColumn col in dt1.Columns)
            {
                newRow[col.ColumnName] = row1[col.ColumnName];
            }
            // 填充dt2的列数据
            newRow["STANJE"] = row2["STANJE"];
            newRow["KOLICINA"] = row2["KOLICINA"];
            mergedTable.Rows.Add(newRow);
        }
    }
    else
    {
        // 5. 无匹配行时,添加默认空值行
        DataRow newRow = mergedTable.NewRow();
        foreach (DataColumn col in dt1.Columns)
        {
            newRow[col.ColumnName] = row1[col.ColumnName];
        }
        newRow["STANJE"] = DBNull.Value;
        newRow["KOLICINA"] = DBNull.Value;
        mergedTable.Rows.Add(newRow);
    }
}

方法二:使用LINQ进行左连接查询

如果你习惯LINQ的写法,这种方式更简洁:

// 将DataTable转为可查询的集合
var dt1Enumerable = dt1.AsEnumerable();
var dt2Enumerable = dt2.AsEnumerable();

// 执行左连接,保留dt1的所有行,并匹配dt2中所有同ROBAID的行
var mergedData = from row1 in dt1Enumerable
                 join row2 in dt2Enumerable
                 on row1.Field<int>("ROBAID") equals row2.Field<int>("ROBAID") into groupedMatches
                 from matchRow in groupedMatches.DefaultIfEmpty()
                 select new
                 {
                     ROBAID = row1.Field<int>("ROBAID"),
                     NAZIV = row1.Field<string>("NAZIV"),
                     STANJE = matchRow != null ? matchRow.Field<int>("STANJE") : (int?)null,
                     KOLICINA = matchRow != null ? matchRow.Field<int>("KOLICINA") : (int?)null
                 };

// 将LINQ查询结果转为DataTable
DataTable mergedTable = new DataTable();
mergedTable.Columns.Add("ROBAID", typeof(int));
mergedTable.Columns.Add("NAZIV", typeof(string));
mergedTable.Columns.Add("STANJE", typeof(int));
mergedTable.Columns.Add("KOLICINA", typeof(int));

foreach (var item in mergedData)
{
    DataRow newRow = mergedTable.NewRow();
    newRow["ROBAID"] = item.ROBAID;
    newRow["NAZIV"] = item.NAZIV;
    newRow["STANJE"] = item.STANJE ?? DBNull.Value;
    newRow["KOLICINA"] = item.KOLICINA ?? DBNull.Value;
    mergedTable.Rows.Add(newRow);
}

关键注意点

  • 如果ROBAID是字符串类型,要修改代码中的Field<int>为Field<string>,同时手动筛选时要给值加单引号(简单场景下直接拼接即可,若需避免注入风险也可使用参数化逻辑)。
  • 两种方法都会保留dt1的所有行,对于dt2中无匹配的ROBAID,STANJE和KOLICINA会设为DBNull.Value,你可以根据需求改成默认值(比如0)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:21:25