【问题标题】:How to write an linq statement to get the last of a group of records如何编写 linq 语句以获取一组记录中的最后一条
【发布时间】:2012-08-13 06:41:11
【问题描述】:

我有 2 个 SQL 语句,它们基本上做同样的事情,即根据一组记录的日期时间字段从表中检索最后一条记录。我正在使用数据优先的实体框架模型。我将如何使用 LINQ Lambda 函数编写这些 SQL 语句?

即,

var u = db.AccessCodeUsage.Where(...).GroupBy(...)

而不是

var u = from a in db.AccessCodeUsage
        where ...
        group by ...

SQL 语句:

SELECT  *
FROM    AccessCodeUsage a  
WHERE   NOT EXISTS (SELECT  1 
                    FROM    AccessCodeUsage 
                    WHERE   LocationId = a.LocationId
                    AND     Timestamp > a.Timestamp)

SELECT    a.*
FROM    AccessCodeUsage a
WHERE   a.Timestamp = 
        (SELECT MAX(Timestamp)
        FROM    AccessCodeUsage
        WHERE   a.LocationId = LocationId
        AND     a.AccessCode = AccessCode
        GROUP   By LocationId, AccessCode)

【问题讨论】:

    标签: c# sql linq entity-framework lambda


    【解决方案1】:

    我最终使用了与第一条 SQL 语句相对应的以下语句。

    // Retrieve only the latest (greatest value in timestamp field) record for each Access Code
    var last = AccessCodeUsages.Where(u1 => !AccessCodeUsages
                               .Any(u2 => u2.LocationId == u1.LocationId &&
                                          u2.AccessCode == u1.AccessCode &&
                                          u2.Timestamp > u1.Timestamp));
    

    【讨论】:

      【解决方案2】:

      如果您需要方法调用形式,但发现它很难解决,请先使用其他语法:

      from a in db.AccessCodeUsage
        orderby a.TimeStamp descending
        group a by a.LocationId into grp
        from g in grp select g.First();
      

      然后通过一次一个地获取每个子句来转换为方法调用:

      db.AccessCodeUsage
        .OrderByDescending(a => a.TimeStamp)
        .GroupBy(a => a.LocationId)
        .Select(g => g.First());
      

      我可以从中锻炼第二个,而无需先写出 linq-syntax 形式:

      db.AccessCodeUsage
        .OrderByDescending(a => a.TimeStamp)
        .GroupBy(a => new {a.LocationId, a.AccessCode})
        .Select(g => g.First());
      

      (除非它不包含可能是错误的内容,因为如果不能保证时间戳是唯一的,则问题中给出的 SQL 可能包含一些额外的不适当结果)。

      我现在无法检查生成的 SQL,但希望它在结果上是等效的(如果不一定匹配)。在某些情况下,分组不能很好地转换为 SQL,但我当然不认为这会是一个。

      【讨论】:

      • 不错的帖子,我也遇到了类似的问题,但是像您所做的那样在 GroupBy() 中使用匿名类型可以让我得到我需要的东西。
      • 酷@PeadarDoyle。我对GroupBy() 给出的一条建议是,如果您不能完全确定如何将其转换为一个不错的单个查询,那么分析它的工作原理总是值得的。某些用途不能只变成一个查询,并且对数据库性能的影响是可怕的(更糟糕的是 - 它通常对测试数据很好,而对真实数据却非常糟糕)。在这个例子中,我会说它可能应该不错,但我还是会检查......
      • 如果您确实发现查询正在变成大量 SQL 查询,请在 .GroupBy() 之前放置 .AsEnumerable()。通常将.AsEnumerable() 放在由 db 支持的 Linq 查询的中间会导致更差的性能(数据库的工作量减少,来自它的流量更多,而 .NET 的工作量更多),但那些不能很好翻译的.GroupBy()是一个例外,在此过程的较早步骤将其移至 .NET 是一种性能优势(也不是小问题,可能是太慢而无用或太快而无法注意到之间的区别)。
      猜你喜欢
      • 2017-05-08
      • 2012-01-23
      • 2017-12-15
      • 2023-01-28
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多