我的C#代码中有Datatable
DataTable 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 // exactly same entry
3 |102 | 202 | some_local_name | 1 |15.30 // exactly same entry
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"
要做的是完全相同但多次输入以合并为一个的记录,但保持其qty
列和price
列更新,例如在上面DaraRows
< strong> id 2和3与id 1 具有完全相同的记录,这应该是一条记录,并通过添加完全相同的重复记录来更新qty
和price
。这应该在同一DataTable
或新版本中更新。
答案 0 :(得分:1)
您可以将DataTable视为可以使用,并使用Linq创建新的DataTable。代码看起来像这样:
DataTable newDt = dt.AsEnumerable()
.GroupBy(r => r.Field<int>("tid"))
.Select(g => {
var row = dt.NewRow();
row["tid"] = g.Key;
row["code"] = g.First(r => r["code"] != null).Field<int>("code");
row["pNameLocal"] = g.First(r => r["pNameLocal"] != null).Field<string>("pNameLocal");
row["qty"] = g.Sum(r => r.Field<int>("qty"));
row["price"] = g.Sum(r => r.Field<double>("price"));
return row;
}).CopyToDataTable();
请参阅下面的示例控制台应用程序,设置示例数据,执行分组以及显示原始数据和结果数据表。
using System;
using System.Data;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var dt = FillUpTestTable();
DumpDataTable(dt);
DataTable newDt = dt.AsEnumerable()
.GroupBy(r => r.Field<int>("tid"))
.Select(g => {
var row = dt.NewRow();
row["tid"] = g.Key;
row["code"] = g.First(r => r["code"] != null).Field<int>("code");
row["pNameLocal"] = g.First(r => r["pNameLocal"] != null).Field<string>("pNameLocal");
row["qty"] = g.Sum(r => r.Field<int>("qty"));
row["price"] = g.Sum(r => r.Field<double>("price"));
return row;
}).CopyToDataTable();
Console.WriteLine();
Console.WriteLine("Result: ");
Console.WriteLine();
DumpDataTable(newDt);
Console.ReadLine();
}
private static DataTable FillUpTestTable()
{
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("tid", typeof(int));
dt.Columns.Add("code", typeof(int));
dt.Columns.Add("pNameLocal", typeof(string));
dt.Columns.Add("qty", typeof(int));
dt.Columns.Add("price", typeof(double));
dt.Rows.Add(1, 101, 101, "some_local_name", 2, 20.36);
dt.Rows.Add(2, 102, 202, "some_local_name", 2, 15.30);
dt.Rows.Add(3, 102, 202, "some_local_name", 2, 15.30);
dt.Rows.Add(4, 102, 202, "some_local_name", 2, 10.00);
dt.Rows.Add(5, 102, 202, "some_local_name", 2, 15.30);
dt.Rows.Add(6, 102, 202, "some_local_name2", 1, 15.30);
dt.Rows.Add(7, 103, 202, "some_local_name", 2, 15.30);
dt.Rows.Add(8, 104, 202, "some_local_name", 2, 05.00);
dt.Rows.Add(9, 105, 202, "some_local_name", 2, 07.01);
return dt;
}
private static void DumpDataTable(DataTable newDt)
{
foreach (DataRow dataRow in newDt.Rows)
{
foreach (var item in dataRow.ItemArray)
{
Console.Write(item + " | ");
}
Console.WriteLine();
}
}
}
}
答案 1 :(得分:1)
你需要在datatable中使用这个:
SELECT tid, code, pNameLocal, sum(qty),sum(price) FROM @tbl
group by tid, code, pNameLocal,qty, price
你可以使用linq。请尝试以下代码。我试图使用你的样本记录。
DataTable dt = new DataTable();
DataColumn[] dcCol = {
new DataColumn("id",typeof(int)),
new DataColumn("tid", typeof(int)),
new DataColumn("code", typeof(int)),
new DataColumn("pNameLocal", typeof(string)),
new DataColumn("qty", typeof(int)),
new DataColumn("price", typeof(decimal))
};
dt.Columns.AddRange(dcCol);
dt.Rows.Add(1, 101, 101, "some_local_name", 2, 20.36);
dt.Rows.Add(2, 102, 202, "some_local_name", 1, 10.00);
dt.Rows.Add(3, 102, 202, "some_local_name", 1, 15.30);
dt.Rows.Add(4, 102, 202, "some_local_name", 1, 10.00);
dt.Rows.Add(5, 102, 202, "some_local_name", 2, 15.30);
dt.Rows.Add(6, 102, 202, "some_local_name2", 1, 15.30);
dt.Rows.Add(7, 103, 202, "some_local_name", 1, 15.30);
dt.Rows.Add(8, 104, 65, "some_local_name", 5, 05.00);
dt.Rows.Add(9, 105, 700, "some_local_name", 2, 07.01);
var dtnew = from r in dt.AsEnumerable()
group r by new
{
tid = r.Field<int>("tid"),
code = r.Field<int>("code"),
pNameLocal = r.Field<string>("pNameLocal"),
qty = r.Field<int>("qty"),
price = r.Field<decimal>("price")
} into grp
select new
{
tid1 = grp.Key.tid,
code1 = grp.Key.code,
pNameLocal1 = grp.Key.pNameLocal,
SumQty = grp.Sum(r => grp.Key.qty),
sumPrice = grp.Sum(r => grp.Key.price)
};
答案 2 :(得分:1)
您可以对包含除计数和价格之外的所有列的匿名类型使用GroupBy
:
var aggregatedRowData = dtDetails.AsEnumerable()
.Select(r => new
{
tid = r.Field<int>("tid"),
code = r.Field<int>("code"),
pNameLocal = r.Field<string>("pNameLocal"),
qty = r.Field<int>("qty"),
price = r.Field<decimal>("price"),
})
.GroupBy(x => new { x.tid, x.code, x.pNameLocal })
.Select(grp => new
{
grp.Key.tid,
grp.Key.code,
grp.Key.pNameLocal,
qty = grp.Sum(x => x.qty),
price = grp.Sum(x => x.price)
});
DataTable aggregatedTable = dtDetails.Clone(); // empty, same columns
foreach (var x in aggregatedRowData)
aggregatedTable.Rows.Add(x.tid, x.code, x.pNameLocal, x.qty, x.price);
答案 3 :(得分:0)
这是你可以做的如果要基于所有列来区分行。
DataTable newDatatable = dt.DefaultView.ToTable(true, "tid", "code", "pNameLocal", "qty", "price");
您在此处提到的列,只有那些将在newDatatable中返回。