代码之家  ›  专栏  ›  技术社区  ›  Ocelot20

获取日期时间为空的计算项的平均值

  •  2
  • Ocelot20  · 技术社区  · 15 年前

    糟糕的标题,我知道…

    这是可行的,给了我我想要的,但我知道一定有更好的方法:

    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();
    

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

    像这样的事情是行不通的:

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

    我知道我见过类似的问题,解决方案是显式地将nullable字段设置为nullable datetime,从而使average方法工作。我 没有 在这样的计算中可以看到空字段。

    事先谢谢。

    编辑: 为了把事情弄清楚一点,让我给你本的解决方案和它产生的错误信息。我不得不承认我遗漏了另一部分……A.其他日期实际上有点棘手……让我举例说明:

    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)。Where(a=>a.ForeignKeyReference.Date.HasValue)。请选择(a=>a.Date.Value.Subtract(a.ForeignKeyReference.Date.Value).Days).Average()”转换为SQL,并且无法将其视为本地表达式。

    似乎“Subtract”方法或“Days”属性没有转换为SQL。我的第一个例子很有效,因为第二个查询是linq to对象。是否有人知道有没有一种方法可以将LINQ查询转换为SQL?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Jonas Elfström    15 年前

    怎么样

    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.");
    
        2
  •  0
  •   Ben    15 年前

    类似这样的技巧确实有用——我已经使用3.5sp1框架验证了输出是否正确:

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

    where()运算符确保.date值为空的任何元素都将从平均值中排除;这是您所指示的行为,对吗?

        3
  •  0
  •   Ocelot20    15 年前

    可能应该更仔细地阅读错误消息。看起来“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();
    

    乔纳斯·埃尔夫斯特¶M的回答是对的,我只是在补充这一点,因为它触及了问题的实际原因。