LINQ和2个数据表

LINQ和2个数据表,linq,Linq,我在一个数据集中有两个数据表。一个表有一个名为CostTypes的列表。只是一个Id和描述字段 另一个数据表是主表,有许多记录,其中一列是成本类型。此数据表中将有未引用的成本类型。这个数据表中还有一列叫做成本 我想做的是按成本类型汇总总成本。但我希望列出的所有成本类型,主表中未列出的任何值都将为零 成本类型表 Id, Description 1,Marketing 2,Sales 3,Production 4,Service 因此,我希望在数据表中看到一个结果(如果可能的话),这样我

我在一个数据集中有两个数据表。一个表有一个名为CostTypes的列表。只是一个Id和描述字段

另一个数据表是主表,有许多记录,其中一列是成本类型。此数据表中将有未引用的成本类型。这个数据表中还有一列叫做成本

我想做的是按成本类型汇总总成本。但我希望列出的所有成本类型,主表中未列出的任何值都将为零

成本类型表

Id, Description

1,Marketing

2,Sales

3,Production

4,Service

因此,我希望在数据表中看到一个结果(如果可能的话),这样我就可以绑定到datagridview

Marketing  130

Sales       0

Production  40

Service     0
谢谢大家的帮助,这是我从答案中得出的结论-有人能提出任何改进吗

如何将查询1中的结果转换为数据表??

  var query1 =
        from rowCT in costTypes.AsEnumerable()
        from rowSTD in stdRates.AsEnumerable()
              .Where( d => d.Field<int?>( "CostTypeId" ) == rowCT.Field<int?>( "CostTypeId" ) )
              .DefaultIfEmpty()
        group new { row0 = rowCT, row1 = rowSTD }
        by rowCT.Field<string>( "Description" ) into g
        select new
        {
            g.Key,
            Cost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "Cost" ) ),
            TotalCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalCost" ) ),
            TotalHours = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalHours" ) ),
            TotalLabourCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalLabourCost" ) )
        }
        ;
var查询1=
来自costTypes.AsEnumerable()中的rowCT
来自stdRates.AsEnumerable()中的rowSTD
其中(d=>d.Field(“CostTypeId”)==rowCT.Field(“CostTypeId”))
.DefaultIfEmpty()
新建组{row0=rowCT,row1=rowSTD}
由rowCT.Field(“Description”)转换为g
选择新的
{
g、 钥匙,
Cost=g.Sum(x=>x.row1==null?0:x.row1.Field(“Cost”),
TotalCost=g.Sum(x=>x.row1==null?0:x.row1.Field(“TotalCost”),
TotalHours=g.Sum(x=>x.row1==null?0:x.row1.Field(“TotalHours”),
TotalAbourCost=g.Sum(x=>x.row1==null?0:x.row1.Field(“TotalAbourCost”))
}
;

您可以使用
Sum
扩展方法来计算成本。如果集合为空,它将返回0,这正是您想要的:

var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");

var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);

var costs = costTypes
  .Rows
  .Cast<DataRow>()
  .Select(
    dr => new {
      Id = dr.Field<Int32>("Id"),
      Description = dr.Field<String>("Description")
    }
  )
  .Select(
    ct => new {
      ct.Description,
      TotalCost = costEntries
        .Rows
        .Cast<DataRow>()
        .Where(ce => ce.Field<Int32>("CostTypeId") == ct.Id)
        .Sum(ce => ce.Field<Int32>("Cost"))
    }
  );
如果上述代码中的
(其中
)执行的线性搜索是一个问题,您可以通过提前创建查找表来提高性能:

var costEntriesLookup = costEntries
  .Rows
  .Cast<DataRow>()
  .Select(
    ce => new {
      Cost = ce.Field<Int32>("Cost"),
      CostTypeId = ce.Field<Int32>("CostTypeId")
    }
  )
  .ToLookup(ce => ce.CostTypeId, ce => ce.Cost);
var costs = costTypes
  .Rows
  .Cast<DataRow>()
  .Select(
    dr => new {
      Id = dr.Field<Int32>("Id"),
      Description = dr.Field<String>("Description")
    }
  )
  .Select(
    ct => new {
      ct.Description,
      TotalCost = costEntriesLookup.Contains(ct.Id)
        ? costEntriesLookup[ct.Id].Sum()
        : 0
    }
  );
var costEntriesLookup=costEntries
.行
.Cast()
.选择(
ce=>新{
成本=成本域(“成本”),
CostTypeId=ce.字段(“CostTypeId”)
}
)
.ToLookup(ce=>ce.CostTypeId,ce=>ce.Cost);
风险价值成本=成本类型
.行
.Cast()
.选择(
dr=>新{
Id=dr字段(“Id”),
Description=dr.Field(“Description”)
}
)
.选择(
ct=>新{
ct.描述,
TotalCost=costEntriesLookup.Contains(ct.Id)
?costEntriesLookup[ct.Id].Sum()
: 0
}
);

可能是这样的:

测试数据:

DataTable dt=new DataTable();
dt.Columns.Add("Id",typeof(int));
dt.Columns.Add("Description",typeof(string));

dt.Rows.Add(1,"Marketing");
dt.Rows.Add(2,"Sales");
dt.Rows.Add(3,"Production");
dt.Rows.Add(4,"Service");

DataTable dt2=new DataTable();
dt2.Columns.Add("Id",typeof(int));
dt2.Columns.Add("Cost",typeof(int));
dt2.Columns.Add("CostTypeId",typeof(int));

dt2.Rows.Add(1,10,1);
dt2.Rows.Add(2,120,1);
dt2.Rows.Add(3,40,1);
Linq查询

var query=(
            from row in dt.AsEnumerable()
            from row1 in dt2.AsEnumerable()
                  .Where (d =>d.Field<int>("Id")==row.Field<int>("Id") )
                  .DefaultIfEmpty()
            group new{row,row1} 
            by row.Field<string>("Description") into g 
            select new
            {
                g.Key,
                Cost=g.Sum (x =>x.row1==null?0:x.row1.Field<int>("Cost"))
            }
            );

我想出了一个比其他人使用的更简单的linq。感谢Martin Liversage提供了创建输入数据的代码

var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");

var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);

var cte = costTypes.Rows.Cast<DataRow>();
var cee = costEntries.Rows.Cast<DataRow>();
var output = cte.Select(
ct => new {
    Description = ct["Description"], 
    Sum = cee.Where(ce=>ce["CostTypeId"].Equals(ct["Id"])).Sum(ce=>(int)ce["Cost"])
    }

);
var costTypes=新数据表(“costTypes”);
costTypes.Columns.Add(“Id”,typeof(Int32));
costTypes.Columns.Add(“Description”,typeof(String));
添加(1,“营销”);
添加(2,“销售”);
成本类型。行。添加(3,“生产”);
添加(4,“服务”);
var costEntries=新数据表(“costEntries”);
costEntries.Columns.Add(“Id”,typeof(Int32));
costEntries.Columns.Add(“成本”,typeof(Int32));
costEntries.Columns.Add(“CostTypeId”,typeof(Int32));
costEntries.Rows.Add(1,10,1);
costEntries.Rows.Add(2120,1);
costEntries.Rows.Add(3,40,3);
var cte=costTypes.Rows.Cast();
var cee=costEntries.Rows.Cast();
var output=cte。选择(
ct=>新{
描述=ct[“描述”],
Sum=cee。其中(ce=>ce[“CostTypeId”]。等于(ct[“Id”])。Sum(ce=>(int)ce[“Cost”])
}
);

在较大的表上,这可能会失去效率,因为每个成本类型都会搜索成本条目表,而使用分组,我怀疑您只需要对该表进行一次遍历。就个人而言,我更喜欢(在我看来)外观更简单的代码。但这取决于您的用例。

我只是认为您没有抓住要点。OP有两个数据表,他想使用它们。您的答案如何适用于此?我的目标是演示如何使用
Sum
执行计算。但是,为了更好地回答这个问题,我将代码改为使用datatables。在我的回答中,我有一些代码演示了如何创建一个
DataTable
DataTable dt=new DataTable();
dt.Columns.Add("Id",typeof(int));
dt.Columns.Add("Description",typeof(string));

dt.Rows.Add(1,"Marketing");
dt.Rows.Add(2,"Sales");
dt.Rows.Add(3,"Production");
dt.Rows.Add(4,"Service");

DataTable dt2=new DataTable();
dt2.Columns.Add("Id",typeof(int));
dt2.Columns.Add("Cost",typeof(int));
dt2.Columns.Add("CostTypeId",typeof(int));

dt2.Rows.Add(1,10,1);
dt2.Rows.Add(2,120,1);
dt2.Rows.Add(3,40,1);
var query=(
            from row in dt.AsEnumerable()
            from row1 in dt2.AsEnumerable()
                  .Where (d =>d.Field<int>("Id")==row.Field<int>("Id") )
                  .DefaultIfEmpty()
            group new{row,row1} 
            by row.Field<string>("Description") into g 
            select new
            {
                g.Key,
                Cost=g.Sum (x =>x.row1==null?0:x.row1.Field<int>("Cost"))
            }
            );
Key        Cost
Marketing  10
Sales      120
Production 40
Service    0
var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");

var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);

var cte = costTypes.Rows.Cast<DataRow>();
var cee = costEntries.Rows.Cast<DataRow>();
var output = cte.Select(
ct => new {
    Description = ct["Description"], 
    Sum = cee.Where(ce=>ce["CostTypeId"].Equals(ct["Id"])).Sum(ce=>(int)ce["Cost"])
    }

);