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

基于时间由LINQ连接到实体(EF)同一表

  •  2
  • Tatranskymedved  · 技术社区  · 8 年前

    我有一张表,里面有关于 time 还有一些 data . 预期结果是 interval (以秒为单位)在两行之间 数据

    MyTable(源):

    ------------------------------
    |        Time        |  Data |
    ------------------------------
    | 23.8.2018 14:00:00 |  abc  |
    | 23.8.2018 14:00:02 |  def  |
    | 23.8.2018 14:00:05 |  ghi  |
    | 23.8.2018 14:00:06 |  jkl  |
    ------------------------------
    

    预期结果:

    -------------------
    | interval| result|
    -------------------
    |    2    |  abc  |
    |    3    |  def  |
    |    1    |  ghi  |
    |   NULL  |  jkl  | --optional result / might not exist
    -------------------
    

    我想可能的解决方案是:

    我的结论是 JOIN ZIP 在LINQ/SQL中。据发现, 拉链 不是Linq对实体的支持,而是应该在局部变量中工作。

    类似于:

    var lTmp = lData.Zip(lData.Skip(1), (a, b) => new
               {
                   interval = (b.Time - a.Time).Seconds,
                   result = a.Value
               }).ToList();
    

    思考 加入 ,我来到了“solution”,在这里我可以在下一行加入同一个表,但我不知道如何用LINQ编写它。考虑到身份证,我 可以加入比前一个大(+1)的ID ,但某些行可能丢失,这些行必须按 Time (不是身份证)。

    SELECT
        DATEDIFF(MILLISECOND,
                 [Time],
                 LEAD([Time], 1, null) OVER (ORDER BY [Time])) AS interval,
        result
    FROM
        Data
    

    问题是:

    可以用LINQ(LINQ to Entities)编写这样的查询吗?如何编写?或者我需要将其放入存储过程/普通SQL查询中?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Richard    8 年前

    LINQ(所有形式)只支持equi连接,所以 join 出局了。

    但您可以自己做一个子查询,以便按时间获取下一行:

    from left in table
    let right = (from x in table
                 where x.Time > left.Time
                 orderby x.Time
                 select x).FirstOrDefault)
    where right != null
    select new {
        left.Data,
        interval = right.Time - left.Time
    }
    

    (您可能需要使用其中一个SQL函数来执行时差。)

    通常,数据库可以优化这样一个相关的子查询,因此性能可能不会太差。否则您可能需要发送自己的SQL。