我有一个大的数据表(500k-1m行),没有详细说明这是一个要求,因为最终用户需要/希望能够看到所有数据。这是在本地服务器上,所以带宽等对我来说不是问题。
我在DataTable中有一个DateTime字段,我需要对其进行分组,让我通过分组来解释我的意思......这可能不是你的意思(从这里查看其他问题!)。
var table = new DataTable();
table.Columns.Add("EventTime", typeof(DateTime));
table.Columns.Add("Result", typeof(String));
table.Columns.Add("ValueOne", typeof(Int32));
table.Columns.Add("ValueTwo", typeof(Int32));
table.Rows.Add("2012-02-06 12:41:45.190", "A", "7", "0");
table.Rows.Add("2012-02-06 12:45:41.190", "B", "3", "89");
table.Rows.Add("2012-02-06 12:59:41.190", "C", "1", "0");
table.Rows.Add("2012-02-06 13:41:41.190", "D", "0", "28");
table.Rows.Add("2012-02-06 17:41:41.190", "E", "0", "37");
table.Rows.Add("2012-02-07 12:41:45.190", "F", "48", "23");
我希望将上表分组,以便得到“ValueOne”列的总和,以及“ValueTwo”列的平均值。我需要分组有点灵活,以便我可以指定我想要按分钟分组(只有第一行和最后一行会被分组,其余行只提供它们的值),或者按天(除了最后一行之外的所有行)将分组为单行)等。
我已经尝试了几次,但我没有在哪里。我的LINQ知识不是很好,但我想我能做到这一点!
注意:DataTable已经在机器上用于无法更改的计算/视图,因此说“停止成为白痴,在SQL中过滤!!!”是一个有效的答案,对我来说没用! :-D
另外,如果你在标题中错过了它,我需要在C#中使用它 - 我正在使用.NET 4.0 ...
提前致谢,假设您决定提供帮助! : - )
答案 0 :(得分:5)
其他三个答案很接近,但正如你所指出的那样,它们分组在同一秒内发生的事件,而不是在同一秒内发生的事件,这就是你想要的。试试这个:
var query = from r in table.Rows.Cast<DataRow>()
let eventTime = (DateTime)r[0]
group r by new DateTime(eventTime.Year, eventTime.Month, eventTime.Day, eventTime.Hour, eventTime.Minute, eventTime.Second)
into g
select new {
g.Key,
Sum = g.Sum(r => (int)r[2]),
Average = g.Average(r => (int)r[3])
};
您可以调整传递给DateTime构造函数的信息,以便按不同的时间部分进行分组。
答案 1 :(得分:1)
您需要更改的唯一内容是您要分组的属性。
var query = from x in DataSource
group x by x.EventTime.Minute into x
select new
{
Unit = x.Key,
SumValueOne = x.Sum(y => y.ValueOne),
AverageValueTwo = x.Average(y => y.ValueTwo),
};
答案 2 :(得分:1)
这样的事情应该有效:
DataTable dt = GetDataTableResults();
var results = from row in dt.AsEnumerable()
group row by new { EventDate = row.Field<DateTime>("EventTime").Date } into rowgroup
select new
{
EventDate = rowgroup.Key.EventDate,
ValueOne = rowgroup.Sum(r => r.Field<int>("ValueOne")),
ValueTwo = rowgroup.Average(r => r.Field<decimal>("ValueTwo"))
};
答案 3 :(得分:0)
以下是基线代码的样子:
var query = table.Rows.Cast<DataRow>()
.GroupBy(r => ((DateTime)r[0]).Second)
.Select(g => new
{
g.Key,
Sum = g.Sum(r => (int)r[2]),
Average = g.Average(r => (int)r[3])
});
为了增加灵活性,你可以这样:
IEnumerable<IGrouping<object, DataRow>> Group(IEnumerable<DataRow> rows, GroupType groupType)
{
// switch case would be preferable, but you get the idea.
if(groupType == GroupType.Minutes) return rows.GroupBy(r => ((object)((DateTime)r[0]).Minute));
if(groupType == GroupType.Seconds) return rows.GroupBy(r => ((object)((DateTime)r[0]).Second));
...
}
var baseQuery = table.Rows.Cast<DataRow>();
var grouped = Group(baseQuery, groupType);
var query = grouped
.Select(g => new
{
g.Key,
Sum = g.Sum(r => (int)r[2]),
Average = g.Average(r => (int)r[3])
});