2013-03-04 108 views
7

我有一张表记录访问期间车辆发生的情况。对于每次访问,都有多行来表示已完成的操作。该表看起来像这样计算不同行中不同列之间的差异

VisitID | ActionID | StartTime | EndTime 
    0 | 0  | 1/1/2013 | 1/2/2013 
    1 | 0  | 1/2/2013 | 1/4/2013 
    1 | 1  | 1/4/2013 | 1/7/2013 
    2 | 0  | 1/4/2013 | 1/5/2013 
    2 | 1  | 1/5/2013 | 1/6/2013 
    2 | 2  | 1/6/2013 | 1/7/2013 

我希望构建一个能够获取访问时间的LINQ查询。 TotalTime通过首先找到第一个和最后(最低和最高)ActionID,然后last.EndTime - first.StartTime来计算。预期结果:

VisitID | TotalTime 
    0 | 1 
    1 | 5 
    2 | 3 

我可以通过做

var first = db.Visits.Where(v => v.ActionID == 0) 
var last = db.Visits.GroupBy(x => x.VisitID).Select(g => g.OrderByDescending(x => x.ActionID).First()) 

first.Join(last, f => f.VisitID, l => l.VisitID, (f, l) new{ VisitID = Key, TotalTime = l.EndTime - f.StartTime}); 

我产生预期的结果我真的不喜欢我以前获得最后ActionID的黑客,我真的希望能够在1条LINQ语句中执行此操作。我需要做些什么才能做到这一点?

回答

4

我认为这应该工作...

var result = db.Visits.GroupBy(v => v.VisitID) 
      .Select(g => new 
        { 
         VisitId = g.Key, 
         TotalTime = g.Max(v => v.EndTime).Subtract(g.Min(v => v.StartTime)).Days 
        }); 

编辑:这是假设actionid不要紧这么多的最大值和最小值开始日期。这里有一个不同的解决方案,其中actionid被排序,第一个和最后一个访问被用来计算时间差。

var result2 = db.Visits.GroupBy(v => v.VisitID) 
      .Select(g => new 
        { 
         VisitId = g.Key, 
         TotalTime = 
        g.OrderBy(v => v.ActionID).Last().EndTime.Subtract(g.OrderBy(v => v.ActionID).First().StartTime).Days 
        }); 
+1

+1另外,我认为他想要总日数,而不是整个时间跨度 – 2013-03-04 22:48:54

+1

@lazyberezovsky良好的捕获。我已更新答案以返回天数。但是,我不确定此查询是否可以与实体框架一起使用,因为这看起来像是一个EF查询。 – 2013-03-04 22:55:23

+1

当然!通过VisitID分组并使用'min'&'max'。布朗尼指出,对于可能含糊不清的问题提供了答案 – Jeff 2013-03-04 23:14:56

0
db.Visits.GroupBy(v => v.VisitID) 
    .Select(g => new { VisitId = g.Key, 
      Days = g.Select(x => x.EndTime.ToOADate()).Sum() 
      -g.Select(x => x.StartTime.ToOADate()).Sum() }); 

用一点点黑客添加的所有天开始和结束天每次访问,并获得差异。

相关问题