2012-04-13 52 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