2013-11-26 138 views
0

我有一个DataTable骨料数据(5分钟)

  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()))) 
         }; 

相当糟糕

回答

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()))) 
      }; 
+0

'ts = g.Key'产生整数;我怎样才能真正获得时间戳(他们应该以5分钟为增量) – Andrew

+0

@Andrew'DateTime'有一个构造函数,它接受许多刻度;不要忘记首先乘以'ticksInFiveMinutes'。 – Servy

+0

我注意到它只是按时间分组,我如何按代理,主机和度量添加附加组? – Andrew

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()))) 
} 
+0

惊艳...我怎么添加5分钟时间戳? – Andrew

+0

散列码就其本质而言将会相互冲突。这根本不处理碰撞。 – Servy

+0

@Andrew:我修改了代码 –