以时间间隔(5分钟)聚合DataTable中的数据

时间:2013-11-26 19:27:13

标签: c# linq datatable aggregation

我有一个DataTable

            DataTable dt = new DataTable();
            dt.Columns.Add("ts");
            dt.Columns.Add("agent");
            dt.Columns.Add("host");
            dt.Columns.Add("metric");
            dt.Columns.Add("val");

我的数据间隔为15秒;我需要为每个主机/代理/指标(包括5分钟时间戳指示符)获得MAX "val",持续5分钟

这是我最粗暴的事情。

        var q1 = from r in dt.Rows.Cast<DataRow>()
                 let ts = Convert.ToDateTime(r[0].ToString())
                    group r by new DateTime(ts.Year, ts.Month, ts.Day, ts.Hour, ts.Minute, ts.Second)
                        into g
                        select new
                        {                                
                            ts = g.Key,
                            agentName = g.Select(r => r[1].ToString()),
                            Sum = g.Sum(r => (int.Parse(r[4].ToString()))),
                            Average = g.Average(r => (int.Parse(r[4].ToString()))),
                            Max = g.Max(r => (int.Parse(r[4].ToString())))
                        };

非常糟糕

2 个答案:

答案 0 :(得分:1)

要按五分钟的间隔对时间进行分组,我们可以简单地将时间中的Ticks除以我们可以预先计算的间隔大小。在这种情况下,它是五分钟内的滴答数:

long ticksInFiveMinutes = TimeSpan.TicksPerMinute * 5;

然后查询变为:

var query = from r in dt.Rows.Cast<DataRow>()
            let ts = Convert.ToDateTime(r[0].ToString())
            group r by new { ticks = ts.Ticks / ticksInFiveMinutes, agent, host }
            into g
            let key = new DateTime(g.Key * ticksInFiveMinutes)
            select new
            {
                ts = key,
                agentName = g.Select(r => r[1].ToString()),
                Sum = g.Sum(r => (int.Parse(r[4].ToString()))),
                Average = g.Average(r => (int.Parse(r[4].ToString()))),
                Max = g.Max(r => (int.Parse(r[4].ToString())))
            };

答案 1 :(得分:0)

以下方法怎么样? 定义GetHashcode方法:

 public DateTime Arrange5Min(DateTime value)
 {
    var stamp = value.timestamp;
    stamp = stamp.AddMinutes(-(stamp.Minute % 5));
    stamp = stamp.AddMilliseconds(-stamp.Millisecond - 1000 * stamp.Second);
    return stamp;
 }

public int MyGetHashCode(DataRow r)
{
        unchecked // Overflow is fine, just wrap
    {
       int hash = 17;
       // Suitable nullity checks etc, of course :)
       hash = hash * 23 + r[1].ToString().GetHashCode();
       hash = hash * 23 + r[2].ToString().GetHashCode();
       hash = hash * 23 + r[3].ToString().GetHashCode();

       var stamp = Arrange5Min(Convert.ToDateTime(r[0].ToString()));

       hash = hash * 23 + stamp.GetHashCode();
       return hash;
    } 
}

从这里借来:What is the best algorithm for an overridden System.Object.GetHashCode?LINQ aggregate and group by periods of time

然后使用Linq中的函数

 var q1 = from r in dt.Rows.Cast<DataRow>()
 group r by MyGetHashCode(r)
 into g
 let intermidiate = new { 
   Row = g.First(), 
   Max = g.Max(v => (int.Parse(r[4].ToString())))
 }
 select 
  new {
    Time = Arrange5Min(Convert.ToDateTime(intermidiate[0].ToString())),
    Host = intermidiate.Row[2].ToString(),
    Agent = intermidiate.Row[1].ToString(),
    Metric = intermidiate.Row[3].ToString(),
    Max = g.Max(v => (int.Parse(r[4].ToString())))
 }