我有一个数据库,它在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查询以从上面的记录中获取平均时间。我尝试了以下方法:
(From o In MYDATA Select o.SleepTo).Average()
由于“SleepTo”是一个日期时间字段,我在Average()上得到一个错误。如果我试图得到一个整数的平均值,上面的linq查询就可以了。
我需要做些什么才能让它适用于日期时间?
答案 0 :(得分:8)
在内部,每个DateTime实际上都存储为多个刻度。 DateTime的Ticks
属性定义为“自1月1日午夜12:00:00起经过的100纳秒间隔的数量”。 (见http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx)
您可以将DateTimes转换为刻度,然后平均,然后转换回日期时间。
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值的平均时间(忽略Date组件),您可以获得恰好时间的刻度:
var averageTicks = (long)(from o in MYDATA select o.SleepTo.TimeOfDay.Ticks).Average();
var averageTime = new TimeSpan(averageTicks);
答案 1 :(得分:4)
这里有几个扩展方法可以帮助解决这个问题...有一个核心问题,如果你在列表中有很多DateTimes,那么ticks(long
vars)的LINQ平均值会溢出
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());
}
答案 2 :(得分:1)
数据库LINQ提供程序似乎不了解如何在绝对日期执行平均值。如果你考虑一下,这是有意义的(平均值是一个总和除以一个数 - 总和是多少?)。
因此,如果您无法运行以下内容:
(From o In MYDATA Select o.SleepTo).Sum()
然后你也无法.Average()
。
由于你想要的实际上是SleepTo的平均时间,你需要得到日期的时间成分作为TimeSpan(时间减去午夜)并平均。你有没有机会SleepFrom
?
与此同时,您可能会发现这篇文章很有启发性:LINQ Average TimeSpan?