从DataTable中删除具有相同列值的行并添加相应的值

时间:2013-08-27 10:35:15

标签: c# linq datatable dataset linq-to-dataset

我有一个包含多列的DataTable。如果某些列的值重复,我需要删除该行并对其添加数量。例如,跟随数据表

ITEM    QTY
------------
1       20
2       10
2       10
3       20

会变成:

ITEM    QTY
-----------
1       20
2       20
3       20

这就是我做的事情

var table = dt.AsEnumerable() 
.GroupBy(row => row.Field("ITEM")) 
.Select(group => group.First()) 
.CopyToDataTable();

它会删除额外的行,但不会累计数量。所以请在这方面帮助我。

3 个答案:

答案 0 :(得分:7)

您可以使用Sum。您只需先找到重复行:

var dupGroups = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"))
    .Where(g => g.Count() > 1);

现在,您可以使用它们来获取总和并从表中删除冗余行。

foreach (var group in dupGroups)
{
    DataRow first = group.First();
    int sum = group.Sum(r => r.Field<int>("QTY"));
    first.SetField("QTY", sum);
    foreach (DataRow row in group.Skip(1))
        dt.Rows.Remove(row);
}

或者在一个创建新DataTable

的查询中
DataTable newTable = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"))
    .Select(g => 
    {
        DataRow first = g.First();
        if (g.Count() > 1)
        {
            int sum = g.Sum(r => r.Field<int>("QTY"));
            first.SetField("QTY", sum);
        }
        return first;
    })
    .CopyToDataTable();

但是,即使是第二种方法也会修改原始表格,因为您使用CopyToDatatable创建新的DataTable,因此可能会有所不同。您需要克隆原始表(DataTable newTable = dt.Clone();)以获取具有相同模式的空表。然后使用NewRow + ItemArray.Clone()table.ImportRow创建真正的克隆而不修改原始数据。

请参阅:C# simple way to copy or clone a DataRow?

编辑:以下是如何在不触及原始表的情况下创建克隆的示例:

DataTable newTable = dt.Clone();
var itemGroups = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"));
foreach (var group in itemGroups)
{
    DataRow first = group.First();
    if (group.Count() == 1)
        newTable.ImportRow(first);
    else
    {
        DataRow clone = newTable.Rows.Add((object[])first.ItemArray.Clone());
        int qtySum = group.Sum(r => r.Field<int>("QTY"));
        clone.SetField("QTY", qtySum);
    }
}

答案 1 :(得分:3)

var table = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")) 
    .Select(group => {
        var row = group.First();
        row['QTY'] = group.Sum(x => x.Field<int>('QTY'));
        return row;
    }).CopyToDataTable();

答案 2 :(得分:1)

这不会改变原来的DataTable

var table = dt.Copy().AsEnumerable()
                      .GroupBy(row=>row["ITEM"])
                      .Select(g=> {
                                DataRow dr = g.First();
                                dr.SetField("QTY", g.Sum(x=>x.Field<int>("QTY")));
                                return dr;
                             })
                      .CopyToDataTable();