2012-04-13 53 views
5

我有了一個DateTime字段下面記錄的數據庫:如何使用LINQ查詢來平均DateTime字段?

2012-04-13 08:31:00.000 
2012-04-12 07:53:00.000 
2012-04-11 07:59:00.000 
2012-04-10 08:16:00.000 
2012-04-09 15:11:00.000 
2012-04-08 08:28:00.000 
2012-04-06 08:26:00.000 

我想運行的LINQ to SQL查詢來獲取從上面記錄的平均時間。我試過以下內容:

​​

由於「SleepTo」是一個日期時間字段,我在Average()上得到一個錯誤。如果我試圖獲得一個整數的平均值,那麼上面的linq查詢就可以工作。

我需要做些什麼才能讓它在日期時間內工作?

+0

您是否有任何可能的SleepFrom值? – yamen 2012-04-13 23:40:24

+0

我想嘗試創建我自己的擴展方法。 – frenchie 2012-04-14 01:51:55

回答

1

數據庫LINQ提供程序似乎並不瞭解如何在絕對日期上執行平均值。如果你仔細想一想,它是有意義的(平均值是一個總和除以一個數 - 總和是多少?)。

所以,如果你不能夠運行以下命令:

(From o In MYDATA Select o.SleepTo).Sum()

那麼你將無法做到.Average()也。

既然你想要的東西實際上是平均時間SleepTo的,你需要得到公正的日期,時間跨度(時間減去午夜也許)的時間分量和平均說。你有沒有機會有SleepFrom

在此期間,你可能會發現這篇文章有啓發:LINQ Average TimeSpan?

+0

我嘗試過Sum,但它也不喜歡日期。我樣本中的數據是我醒來的時候。我試圖讓我醒來的平均時間。 – Jade 2012-04-13 23:34:32

+0

這就是我的觀點,總和不會工作 - 因此平均也不會工作。你最好的辦法是去掉日間組件,然後花時間。將其轉化爲午夜的時間跨度,然後您可以獲得平均值。這會給你你的平均覺醒時間(AM)。看到我發佈的鏈接。 – yamen 2012-04-13 23:36:32

+0

更新了我的回答,詢問您是否擁有'SleepFrom'(這會讓一切變得簡單)或者如果您只想從午夜開始的時間?也就是說,你想知道你醒來的平均時間,或者你平均睡眠的時間? – yamen 2012-04-14 22:36:50

8

內部,每個日期時間真的存儲爲一個編號蜱。 DateTime的Ticks屬性被定義爲自0001年1月1日午夜12:00:00開始經過的100納秒間隔的數量。 (請參閱http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx

您可以將日期時間轉換爲刻度,然後平均值,然後再轉換回日期時間。

var averageTicks = (long) dates.Select(d => d.Ticks).Average(); 
var averageDate = new DateTime(averageTicks); 

使用你的數據結構和格式,它應該是這樣的:

var averageTicks = (long)(from o in MYDATA select o.SleepTo.Ticks).Average(); 
var averageDate = new DateTime(averageTicks); 

如果你想獲得每個SleepTo值的平均時間(忽略日期部分),就可以得到只是時間刻度:

var averageTicks = (long)(from o in MYDATA select o.SleepTo.TimeOfDay.Ticks).Average(); 
var averageTime = new TimeSpan(averageTicks); 
+0

這不會給出想要的答案,因爲問題與SleepTo的平均時間*,而不是平均日期時間有關。我會認真地推薦自午夜以來將SleepTo轉換爲TimeSpan(甚至自午夜以來的Ticks),然後對其進行平均,否則所有答案都是錯誤的。 – yamen 2012-04-14 22:16:59

+0

Jade原始文章中的代碼示例和最後一個問題讓我相信他或她正在尋求求平均'DateTime'的幫助。基於你的建議@yamen,我添加了一個新的片段來平均時間組件。謝謝! – 2012-04-14 22:42:43

+0

好的加法,upvoted! – yamen 2012-04-14 22:47:32

4

這裏有幾個分機的方法,可以幫助這一點...有一個核心問題:如果你有很多DateTime是否在列表中的LINQ平均的中蜱(long變量)將溢出。

public static long Average(this IEnumerable<long> longs) 
    { 
     long count = longs.Count(); 
     long mean = 0; 
     foreach (var val in longs) 
     { 
      mean += val/count; 
     } 
     return mean; 
    } 

    public static DateTime Average(this IEnumerable<DateTime> dates) 
    { 
     return new DateTime(dates.Select(x => x.Ticks).Average()); 
    } 
+0

+1。謝謝。當項目數量足夠大時,這是對接受答案的改進。 – MickyD 2015-09-03 06:12:40

+0

非常感謝!好的改進! – klutch1991 2017-03-17 09:34:59

+0

我認爲這可能會累積一個錯誤,因爲你正在使用val/count的整數除法。嘗試使用新的平均值[] {3l,5l,7l} - 正確的平均值是5,你會得到4.我相信你應該使用中間數學的雙打。我更喜歡在擴展Linq時使用Linq,因爲它更難理解:) public static long Average(this IEnumerable longs){ \t \t var count = longs.Count(); (long)(long .Aggregate(0.0,(r,l)=> r + =(double)l/count)); } – NetMage 2017-04-07 22:17:19