Linq 语法查找 DataTable 中分组行的小计并更新 DataTable

Linq syntax to find subtotal of grouped rows in a DataTable and update the DataTable

我一直在为这个问题挠头...我在内存中有一个table,一个结构如下的DataTable:

Input:
   ID   |   Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
    0    |   09310   |    123    |    6.0    |    ?
-----------------------------------------------------------------

并且我希望使用 Linq 执行以下操作(我对 Linq 还很陌生!)

对于同一账户的每一行,将所有付款加在一起并写入或更新小计字段 我不想折叠 table,发票编号会有所不同。我的想法是有两种方法可以做到这一点

(A) 从所有记录的空白小计列开始...来自付款的值将被加在一起,然后写入小计列

(B) 当 table 创建时,我将付款值复制到小计字段中。稍后,linq 只需 add/replace 同一列中的值

因此我们将忽略 ID 和 Invoice 字段;它的 ACCOUNT 和 SUBTOTAL(如果使用样式 (A),还有 PAYMENT)

(A) Input: *(note that there are two records for 123)*
   ID   |   Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
    0    |   03310   |    123    |    6.0    |    
-----------------------------------------------------------------
    1    |   09728   |    123    |    4.0    |    
-----------------------------------------------------------------
    2    |   07731   |    559    |    18.0   |    
-----------------------------------------------------------------

(B) Input:
   ID   |   Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
    0    |   03310   |    123    |    6.0    |    6.0
-----------------------------------------------------------------
    1    |   09728   |    123    |    4.0    |    4.0
-----------------------------------------------------------------
    2    |   07731   |    559    |    18.0   |    18.0
-----------------------------------------------------------------

Result:
   ID   |   Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
    0    |   03310   |    123    |    6.0    |    10.0
-----------------------------------------------------------------
    1    |   09728   |    123    |    4.0    |    10.0
-----------------------------------------------------------------
    2    |   07731   |    559    |    18.0   |    18.0
-----------------------------------------------------------------

因此,每个小计单元格将包含每个唯一帐户的所有付款总额

我认为样式 (B) 会更简单,因为我们只需要处理这两列

对于样式(B),我尝试过类似

rpTable.AsEnumerable().GroupBy(g => int.Parse(g.Field<string>("Account"))).Select(g => g.Sum(p => p.Field<decimal>("SubTotal")));

但我可以看出它缺少了一些东西.....嗯嗯

通过使用 Select,您将不会更新 table。这只是 returns 所选值的 IEnumerable。

您要做的是将列添加到 table,然后填写它:

var subTotalByAccount = table.AsEnumerable()
            .GroupBy(g => g.Field<string>("Account"))
            .Select(g => new { Account = g.Key, SubTotal = g.Sum(p => p.Field<decimal>("Payment")) })
            .ToDictionary(t => t.Account, t => t.SubTotal);

table.Columns.Add("SubTotal", typeof(decimal));
foreach (var row in table.AsEnumerable())
{
            row.SetField(columnName: "SubTotal", value: subTotalByAccount[row.Field<string>("Account")]);
}

非常感谢timcbaoth,是的,我同意你说的。我试图给你的 post 投票,但系统说我可能不会:-(
我已经使用蛮力解决了(下面),但我也会评估您的解决方案!再次感谢!!

        var query = from row in rpTable.AsEnumerable()
                    group row by int.Parse(row.Field<string>("Account")) into grp
                    orderby grp.Key
                    select new
                    {
                        Id = grp.Key,
                        Sum = grp.Sum(r => r.Field<decimal>("Payment"))
                    };
        foreach (var grp in query)
        {
            rpTable.Select("Account ="+grp.Id).ToList<DataRow>().ForEach(r=>r["Payment"] = grp.Sum);
        }

我发现了一个隐藏的小错误,所以仅供参考:

OLD: rpTable.Select("Account ="+grp.Id).ToList<DataRow>().ForEach(r=>r["Payment"] = grp.Sum);   
NEW: rpTable.Select("Account ='"+ grp.Id +"'").ToList<DataRow>().ForEach(r => r["Payment"] = grp.Sum);