完全披露,我对linq来说几乎是一个完全的noob。我可以根据我应该如何接近这一点。
我有{3}的DataTable
的oid,IDATE,量
每个ID都有多个日期,每个日期都有多个金额。我需要做的是为每个id总计每天的金额,而不是:
我会:
private void excelDaily_Copy_Into(DataTable copyFrom, DataTable copyTo)
{
var results = from row in copyFrom.AsEnumerable()
group row by new
{
oid = row["oid"],
idate = row["idate"]
} into n
select new
{
///unsure what to do
}
};
我已经尝试了十几种不同的方式来做这件事,我总是碰到一堵墙,在那里我无法弄清楚如何进步。我一直在堆栈溢出和msdn,到目前为止没有任何东西真的帮助了我。
提前谢谢!
答案 0 :(得分:2)
你可以试试这个:
var results = from row in copyFrom.AsEnumerable()
group row by new
{
oid = row.Field<int>("oid"),// Or string, depending what is the real type of your column
idate = row.Field<DateTime>("idate")
} into g
select new
{
g.Key.oid,
g.Key.idate,
SumOfAmounts=g.Sum(e=>e.Field<decimal>("amount"));
};
我建议使用Field扩展方法,该方法提供对指定行中每个列值的强类型访问。
答案 1 :(得分:1)
虽然你没有指定它,但显然copyFrom是一个实现IEnumerable的类DataTable中的对象。
根据MSDN System.Data.DataTable,班级没有实施。如果使用该类,则需要属性Rows,它返回实现IEnumerable的行集合:
IEnumerable<DataRow> rows = copyFrom.Rows.Cast<DataRow>()
但是如果你使用不同的DataTable类,你可能会做类似的事情,把它投射到一系列DataRow。
System.Data.DataRow类的对象具有用于访问行中列的项属性。在您的情况下,列名称是oid,idate和amount。
要将copyFrom转换为您要进行处理的项目序列,请执行以下操作:
var itemsToProcess = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Oid = row["oid"],
Date = (DateTime)row["idate"],
Amount = (decimal)row["amount"],
});
我不确定,但我认为列idate包含日期,列数量包含一些值。如果您的列包含其他类型,请随意使用其他类型。
如果您的列包含字符串,请使用Parse:
将它们转换为正确的项目var itemsToProcess = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Id = (string)row["oid"],
Date = DateTime.Parse( (string) row["idate"]),
Amount = Decimal.Parse (string) row["amount"]),
});
如果您不熟悉lambda表达式。它帮助我阅读如下:
itemsToProcess是一组项目,取自集合 DataRows,我们在这个集合的每一行创建了一个新的 具有三个属性的对象:Id = ...;数据= ......;金额= ...
见
现在我们有一个序列,我们可以比较日期和总和金额。
您想要的是将此序列中的所有项目分组到具有相同ID和日期的组中。所以你想要一个Id = 00045和Date = 02/13/2011的小组,以及一个Id = 00045和date =,02 / 14/2011的小组。
为此,您使用Enumerable.GroupBy。作为选择器(=一个组中共有所有项目的共同点),您可以使用Id和Date的组合:
var groups = itemsToProcess.GroupBy(item => new
{Id = item.Id, Data = item.Data} );
现在你有了小组。
所以你要做的就是对每组中序列中的所有元素求和。
var resultSequence = groups.Select(groupItem => new
{
Id = groupItem.Key.Id
Date = groupItem.Key.Date,
Sum = groupItem.Sum(itemToProcess => itemToProcess.Value,
}
所以把它们放在一个声明中:
var resultSequence = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Id = (string)row["oid"],
Date = DateTime.Parse( (string) row["idate"]),
Amount = Decimal.Parse (string) row["amount"]),
})
.GroupBy (itemToProcess => new
{
Id = item.Id,
Data = item.Data
});
.Select(groupItem => new
{
Id = groupItem.Key.Id
Date = groupItem.Key.Date,
Sum = groupItem.Sum(itemToProcess => itemToProcess.Value,
});