使用LINQ合并数据表记录

时间:2014-01-10 12:02:30

标签: c# linq linq-to-sql

我有一个DataTable,如下所示,

Company      Manager       Location      Count1      Count2      Count3
------------ ------------- ------------- ----------- ---------- --------
C1           Mgr           LocName       1           0            0  
C1           Mgr           LocName       0           3            0
C1           Mgr           LocName       0           0            7
C2           Mgr2          LocName2      0           0            5

但是,我想将此表显示为

Company      Manager       Location      Count1      Count2      Count3
------------ ------------- ------------- ----------- ---------- --------
C1           Mgr           LocName       1           3            7  
C2           Mgr2          LocName2      0           0            5  

任何人都可以帮助我...... 谢谢你。

2 个答案:

答案 0 :(得分:2)

按三列(公司,经理,位置)对行进行分组,并计算计数字段的总和:

var query = from r in table.AsEnumerable()
            group r by new { 
               Company = r.Field<string>("Company"),
               Manager = r.Field<string>("Manager"),
               Location = r.Field<string>("Location")
            } into g
            select new {
               g.Key.Company,
               g.Key.Manager,
               g.Key.Location,
               Count1 = g.Sum(r => r.Field<int>("Count1"),
               Count2 = g.Sum(r => r.Field<int>("Count2"),
               Count3 = g.Sum(r => r.Field<int>("Count3")
            };

使用自定义CopyToDataTable()方法为自定义类型创建新的DataTable(如果您需要DataTable)来自此查询:

DataTable result = query.CopyToDataTable();

如果可以在服务器端使用Linq to Sql进行分组,那么查询将如下所示:

var query = from x in db.TableName
            group r by new { 
               x.Company,
               x.Manager,
               x.Location
            } into g
            select new {
               g.Key.Company,
               g.Key.Manager,
               g.Key.Location,
               Count1 = g.Sum(x => x.Count1),
               Count2 = g.Sum(x => x.Count2),
               Count3 = g.Sum(x => x.Count3)
            };

在这种情况下,您将避免在客户端上下载所有数据和计算。

答案 1 :(得分:1)

您可以使用Enumerable.GroupBy + Sum

var companyGroups = tblCompany.AsEnumerable()
    .GroupBy(row => new {
        Company = row.Field<string>("Company"),
        Manager = row.Field<string>("Manager"),
        Location = row.Field<string>("Location"),
    });
// creates an empty DataTable with the same columns:
var merge = tblCompany.Clone();  
foreach(var companyGroup in  companyGroups)
{
    merge.Rows.Add(
        companyGroup.Key.Company,
        companyGroup.Key.Manager,
        companyGroup.Key.Location,
        companyGroup.Sum(row => row.Field<int>("Count1")),
        companyGroup.Sum(row => row.Field<int>("Count2")),
        companyGroup.Sum(row => row.Field<int>("Count3")));
}

您的样本数据会产生所需的结果:

var tblCompany = new DataTable();
tblCompany.Columns.Add("Company", typeof(string));
tblCompany.Columns.Add("Manager", typeof(string));
tblCompany.Columns.Add("Location", typeof(string));
tblCompany.Columns.Add("Count1", typeof(int));
tblCompany.Columns.Add("Count2", typeof(int));
tblCompany.Columns.Add("Count3", typeof(int));

tblCompany.Rows.Add("C1", "Mgr", "LocName", 1, 0, 0);
tblCompany.Rows.Add("C1", "Mgr", "LocName", 1, 3, 0);
tblCompany.Rows.Add("C1", "Mgr", "LocName", 0, 0, 7);
tblCompany.Rows.Add("C2", "Mgr2", "LocName2", 0, 0, 5);

如果您想要获取每个组的第一个值!= 0

foreach (var companyGroup in companyGroups)
{
    merge.Rows.Add(
        companyGroup.Key.Company,
        companyGroup.Key.Manager,
        companyGroup.Key.Location,
        companyGroup
            .Select(row => row.Field<int>("Count1"))
            .Where(i => i != 0)
            .FirstOrDefault(),
        companyGroup
            .Select(row => row.Field<int>("Count2"))
            .Where(i => i != 0)
            .FirstOrDefault(),
        companyGroup
            .Select(row => row.Field<int>("Count3"))
            .Where(i => i != 0)
            .FirstOrDefault());
}

为了完整起见,如果您需要修改原始表而不是创建新表:

foreach (var companyGroup in companyGroups)
{
    // modify just the first row of each group, 
    // all others will be removed after the merge
    DataRow first = companyGroup.First();
    first.SetField("Count1", companyGroup.Sum(row => row.Field<int>("Count1")));
    first.SetField("Count2", companyGroup.Sum(row => row.Field<int>("Count2")));
    first.SetField("Count3", companyGroup.Sum(row => row.Field<int>("Count3")));
    foreach (DataRow other in companyGroup.Skip(1))
        tblCompany.Rows.Remove(other);
}
相关问题