2012-08-16 68 views
2

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

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) 

回答

0

我结束了使用以下对应于第一个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)); 
3

如果您需要有方法调用的形式,但发现它非常棘手的工作out,则先使用其他语法:

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的语法形式第一:

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

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

我无法检查现在生成的SQL,但它应该有望在结果上相当(如果不一定匹配)。有些情况下,分组不会转换为SQL,但我当然不会认为这将是一个。

+0

好帖子,我有一个类似的问题,但在GroupBy()中使用匿名类型,因为你已经允许我得到我需要的。 – 2012-08-17 09:08:12

+0

酷@PeadarDoyle。我用'GroupBy()'给出的一条建议是,如果你不确定如何将它转换成一个好的单个查询,总是值得分析它是如何工作的。有些使用不能变成只有一个查询,并且对数据库性能的影响是可怕的(更糟糕的是,它对测试数据通常很好,对实际数据的损害也很小)。在这个例子中,我会说它*可能*应该是好的,但我会检查反正... – 2012-08-17 09:14:54

+0

如果你*发现查询被转换成大量的SQL查询把'.AsEnumerable()'之前'.GroupBy()'。通常情况下,将'.AsEnumerable()'放到支持数据库的Linq查询中,会导致性能下降(数据库工作量减少,流量增加,.NET工作量增加),但是'.GroupBy()'那些不能很好地转换的是一个例外,在这个过程的早期步骤中将它移动到.NET是一个性能上的胜利(不是很小的一个,可能是因为太慢而无法用于快速注意)。 – 2012-08-17 09:17:33

相关问题