2013-11-26 85 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:我修改了代碼 –