【问题标题】:Conditions and merge on Datatables while data replacement from one to another数据表的条件和合并,同时数据从一个到另一个替换
【发布时间】:2018-03-22 05:08:25
【问题描述】:

我的 C# Windows 窗体应用程序中有两个数据表;

DataTable dtProduct;
DataTable dtDetails;

dtProduct 是从 MS Access 填充的,dtDetails 是从 MySql 填充的,它们有以下类似记录

dtProduct

code   | pNameOrignal
----------------------
101    | product one
220    | product two 
65     | product three
104    | product four
221    | product five 
654    | product six

dtDetails

id | tid | code | pNameLocal        | qty | price
-------------------------------------------------
1  |101  | 101  | some_local_name   | 2   |20.36
2  |102  | 202  | some_local_name   | 1   |15.30 // same entry as same tid and all same 
3  |102  | 202  | some_local_name   | 1   |15.30 //same entry as same tid and all same
4  |102  | 202  | some_local_name   | 1   |10.00 //same entry as same tid but price is different
5  |102  | 202  | some_local_name   | 2   |15.30 //same entry as same tid but different qty
6  |102  | 202  | some_local_name2  | 1   |15.30 //same entry as same tid but pNameLocal different
7  |103  | 202  | some_local_name   | 1   |15.30 // different entry of same product see different tid
8  |104  | 65   | some_local_name   | 5   |05.00
9  |105  | 700  | some_local_name   | 2   |07.01 // does not exist in "dtProduct"

我目前正在使用dtProduct 循环遍历dtdetails 的所有记录,以根据两个表中code 列的唯一性从dtProduct 替换产品的原始名称pNameOrignal。我现有的代码如下所示;

dtDetails.Rows
    .Cast<DataRow>()
    .Join
    (
        dtProduct.Rows.Cast<DataRow>(),
        r1 => new { p1 = r1["code"], p2 = r1["code"] },
        r2 => new { p1 = r2["code"], p2 = r2["code"] },
        (r1, r2) => new { r1, r2 }
    )
    .ToList()
    .ForEach(o => o.r1.SetField("pNameLocal", o.r2["pNameOrignal"]));

现在需要什么

  1. 需要通过将 qty 设置为 2(如在当前记录中) 将具有 same tid and all same 的相同条目合并或生成一行和价格为 30.60(根据当前记录)

    说明: 将完全相同(重复)的多条记录合并为一行,按记录数量保留其数量和价格。

  2. 针对具有code = 700tid = 105 的条目在dtProduct 中不存在,它不会从那里替换pOrignalName,将保持与当前我的代码相同的名称,我需要使用该名称添加或连接“NotFound”。

【问题讨论】:

  • @JohnWu 我试图找到重复的行,但无法将它们合并为一个。并且只是想在 foreach 中为第 2 点设置一些条件。
  • 我不知道为什么投票给关闭?

标签: c# .net linq


【解决方案1】:

对于第二点,用匹配的记录替换名称并为不匹配的记录添加“NotFound”。

 var k =  (from d in dtDetails.AsEnumerable() join
         k1 in dtProduct.AsEnumerable() on d["code"] equals k1["code"] into dk1
         from subset in dk1.DefaultIfEmpty()
         select new { d, subset }).ToList();

foreach (var m in k)
{
    if (m.subset != null)
    {
        if (string.Equals(m.d["code"], m.subset["code"]))
        {
            m.d.SetField("pNameLocal", m.subset["pNameOrignal"]);
        }
    }
    else
    {
        m.d.SetField("pNameLocal", m.d["pNameLocal"] +"NotFound");
    }
}

第一个试试这个

   dtDetails = dtDetails.AsEnumerable()
    .GroupBy(r => new { Col1 = r["tid"], Col2 = r["code"], Col3 = r["pNameLocal"] })
    .Select(g =>
    {
        var row1 = dtDetails.NewRow();

        row1["tid"] = g.Key.Col1;
        row1["code"] = g.Key.Col2;
        row1["pNameLocal"] = g.Key.Col3;
        row1["qty"] = g.Sum(r => r.Field<int>("qty"));
        row1["price"] = g.Sum(r => r.Field<decimal>("price"));

        return row1;
    })
    .CopyToDataTable();

【讨论】:

  • 你的 foeach 可以简化为: foreach (var m in k) { var pNameOrginal = m.subset != null && string.Equals(m.d["code"], m.subset["code "]) ? m.subset["pNameOrignal"] : "未找到"; m.d.SetField("pNameLocal", pNameOrginal); }
  • @trighati - 请检查这两点的更新答案,让我知道它是否有效,
【解决方案2】:

对于您提到的第 2 点,可以这样做:

foreach (DataRow item in dtDetails.Rows)
{
  var pNameOriginal = dtProduct.AsEnumerable().FirstOrDefault(i => i.Field<int>("code") == item.Field<int>("code"));
  var globalName = "NotFound";
  if (pNameOriginal != null && !string.IsNullOrEmpty(Convert.ToString(pNameOriginal.ItemArray[1])))
  {
    globalName = Convert.ToString(pNameOriginal.ItemArray[1]);
  }

  item["pNameLocal"] += globalName;
}

我仍然不清楚您在第 1 点中想要什么。在您的情况下,group by 的计数怎么可能是 2。你能用 tid 102 解释一下吗?

【讨论】:

  • 对于第 1 点,有两个具有相同记录的条目,我需要将它们设为一个并仅合计它们的数量和价格。我认为这两个事务是分开完成的,这是存储此记录的现有程序中的缺陷。现在我的要求是使其成为单行,但数量和价格应该合并。
  • item["pNameLocal"] = globalName; 这将设置为 NotFound,我想将 NotFound 与其本地名称连接
  • 根据您的解释,这意味着对于 102 | 202,数量将是 6(102 所有数量的总和),价格将是 102 所有价格的总和?
  • 没有。只有102的总和| 102 其中 pNameLocal、数量和价格完全相同。在其他 4 个条目中,价格、数量和名称与前两个条目不同。我只想合并为单个并将它们的数量和价格添加到前两行的单行中
  • 请在上面的评论中更正:没有。只有 102 的总和 | 202 其中......
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 2018-08-09
相关资源
最近更新 更多