使用Nullable DateTime获取计算项的平均值

时间:2010-09-30 20:38:13

标签: c# sql linq linq-to-sql

可怕的头衔,我知道......

这有效,并且给了我正在寻找的东西,但我知道必须有更好的方法来做到这一点:

var query = (from a in DB
             where a.Date.HasValue
             select a).AsEnumerable();

double avg = (from a in query
              select (a.Date.Value.Subtract(a.OtherDate).Days).Average();

基本上,a.Date是一个可以为空的日期时间,我想只在a.Date存在时得到(a.Date - a.OtherDate)的平均值(否则计算不起作用)。

这样的事情不起作用:

double avg = (from a in DB
              where a.Date.HasValue
              select a.Date.Value.Subtract(a.OtherDate).Days).Average();

我知道我已经看到类似的问题,解决方案是将可空字段显式设置为可为空的日期时间,使得Average方法有效。我没有看到可空字段是这样计算的一部分。

提前致谢。

编辑:为了清理一下,让我给你Ben的解决方案及其生成的错误消息。我不得不承认我离开了它的另一部分... a.OtherDate实际上有点棘手......让我说明一下:

var avg = DB.Where(a => a.Date.HasValue)
            .Where(a => a.ForeignKeyReference.Date.HasValue)
            .Select(a => a.Date.Value.Subtract(a.ForeignKeyReference.Date.Value).Days)
            .Average();

......和错误:

InvalidOperationException:无法翻译表达式'Table(DB).Where(a => a.Date.HasValue)。其中(a => a.ForeignKeyReference.Date.HasValue)。选择(a => a .Date.Value.Subtract(a.ForeignKeyReference.Date.Value).Days).Average()'进入SQL并且无法将其视为本地表达式。

好像“Subtract”方法或“Days”属性没有转换为SQL。我的第一个例子有效,因为第二个查询是对象的LINQ。有没有人知道是否有办法以一种转换为SQL的方式编写LINQ查询?

3 个答案:

答案 0 :(得分:2)

怎么样

double AvgDays = dates.Where(d => d.Date.HasValue)
                        .Average(dd => (dd.Date.Value-dd.OtherDate).Days);

但也许这样的事情更有用

var ticks = (long)dates.Where(d => d.Date.HasValue)
                        .Average(dd => (dd.Date.Value - dd.OtherDate).Ticks);

var avg = new TimeSpan(ticks);

Console.WriteLine("It's " + avg.Days + " days and " + avg.Hours + " hours and " + avg.Seconds + " seconds.");

答案 1 :(得分:0)

这样的事情确实有用 - 我已经使用3.5 sp1框架验证输出是正确的:

var avg = DB
    .Where(a => a.Date.HasValue)
    .Select(a => a.Date.Value.Subtract(a.OtherDate).Days)
    .Average();

Where()运算符确保具有空值的任何元素将从平均值中排除;这是你表示你想要的行为,对吗?

答案 2 :(得分:0)

可能应该稍微阅读错误消息。看起来没有“Subtract”方法的SQL转换,但实际上你可以简单地从另一个中减去一个日期来创建一个日期时间,如下所示:

var query = from a in DB
            select (a.Date.Value - a.ForeignKeyReference.Date.Value);

意思是解决方案是:

var query = (from a in DB
             where a.Date.HasValue
             where a.ForeignKeyReference.Date.HasValue
             let ts = (TimeSpan)(a.Date.Value - a.ForeignKeyReference.Value)
             select ts.Days).Average();

JonasElfström的回答是正确的,我只是添加了这个,因为它打击了问题的实际原因。