如何使用Groupby和Linq对DataTable中的多个列的值求和

时间:2017-03-24 04:38:38

标签: c# linq datatable group-by sum

我有一个简单的DataTable如下:

column1 value1  value2
ee      1       2
ee      2       4
ee1     3       6
ee2     3       3
ee2     4       2

我希望每个colunm1得到value1和value2的总和,最后得到一个新的DataTable,如下所示:

column1 value1  value2
ee      3       6
ee1     3       6
ee2     7       5

s not too difficult to realize by a loop of calculation in a traditional way. I want to realize that as simple as possible in a Linq way. I have a existed solution, but I don非常喜欢它。特别是,在这里我不得不使用Foreach来实现它,它有点奇怪。

var resultDt = dtIn.Clone();
dtIn.Select().GroupBy(m=>m["column1"].ToString())
             .Select(n=>new 
                          { Row = n.First(),
                            Value1 = n.Sum(s=>(int)s["value1"]),
                            Value2 = n.Sum(s=>(int)s["value2"])
                          })
             .ToList()
             .ForEach(m=>
                      {
                          var drNew = m.Row;
                          drNew["value1"] = m.Value1; 
                          drNew["value2"] = m.Value2;
                          resultDt.Rows.Add(drNew);
                      }); 

有人可以给我一个暗示吗?

3 个答案:

答案 0 :(得分:2)

使用CopyToDataTable

var resultDt = dtIn.AsEnumerable().GroupBy(m=>m.Field<string>("column1"))
                 .Select(n=>new 
                              { column1  = n.Key,
                                Value1 = n.Sum(s=>s.Field<int>("value1")),
                                Value2 = n.Sum(s=>s.Field<int>("value2"))
                              }).CopyToDataTable();

答案 1 :(得分:1)

这里尝试一下,这应该适合你:

DataTable dt = new DataTable();
dt.Columns.Add("column1");
dt.Columns.Add("value1", typeof(int));
dt.Columns.Add("value2", typeof(int));

dt.Rows.Add("ee", 1, 2);
dt.Rows.Add("ee", 2, 4);
dt.Rows.Add("ee1", 3, 6);
dt.Rows.Add("ee2", 3, 3);
dt.Rows.Add("ee2", 4, 2);

var items = dt.AsEnumerable().GroupBy(
            x => x.Field<string>("column1")
    ).Select
    (
        n => new
        {
            column1 = n.Key,
            value1 = n.Sum(z => z.Field<int>("value1")),
            value2 = n.Sum(z => z.Field<int>("value2"))
        }
    )
    .ToList();

答案 2 :(得分:0)

更聪明的方法通常是在数据库端进行聚合以避免填充不必要的数据。

循环可以隐藏在.Aggregate

var result = dt.Rows.Cast<DataRow>().ToLookup(r => r[0] as string).Aggregate(dt.Clone(),
    (t, g) => t.Rows.Add(g.Key, g.Sum(r => (int)r[1]), g.Sum(r => (int)r[2])).Table);

或多列更复杂:

DataTable result = dt.Rows.Cast<DataRow>().ToLookup(r => r[0])
    .Aggregate(dt.Clone(), (t, g) => t.Rows.Add(Enumerable.Range(0, t.Columns.Count)
    .Select(i => i < 1 ? g.Key : g.Sum(r => (int)r[i])).ToArray()).Table);
Debug.Print(string.Join("\t", result.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
Debug.Print(string.Join("\n", result.Rows.Cast<DataRow>().Select(r => string.Join("\t\t", r.ItemArray))));