2013-03-04 12 views
7

Ich habe eine Tabelle, die aufzeichnet, was mit einem Fahrzeug während eines Besuchs passiert. Für jeden Besuch gibt es mehrere Zeilen, um anzuzeigen, was getan wurde. Die Tabelle sieht wie folgt ausBerechnung der Differenz zwischen verschiedenen Spalten in verschiedenen Zeilen

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 

Ich möchte eine LINQ-Abfrage zu konstruieren, der Lage, immer einen Besuch nahm die Menge an Zeit. TotalTime wird berechnet, indem zuerst die erste und letzte (niedrigste und höchste) ActionID, dann last.EndTime - first.StartTime gefunden wird. Erwartete Ergebnisse:

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

Ich kann meine erwarteten Ergebnisse erzeugen, indem

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

tun Ich mag es nicht wirklich den Hack, den ich verwendet, um die letzte ActionID zu bekommen, und ich würde wirklich in der Lage sein möchte tue dies innerhalb von 1 LINQ-Anweisung. Was muss ich tun, um dies zu erreichen?

Antwort

4

Ich denke, das sollte funktionieren ...

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

Edit: Das übernimmt die ActionID spielt keine Rolle, so viel wie die Maximal- und Minimaldaten beginnen. Hier ist eine andere Lösung, bei der die Aktionseinheiten geordnet sind und die ersten und letzten Besuche zur Berechnung der Zeitdifferenz verwendet werden.

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 Auch ich denke, er will totaldays, nicht ganze Zeitspanne –

+1

@lazyberezovsky Guter Fang. Ich habe die Antwort aktualisiert, um die Anzahl der Tage zurückzugeben. Ich bin jedoch nicht sicher, ob diese Abfrage mit Entity Framework funktioniert, da dies wie eine EF-Abfrage aussieht. –

+1

Natürlich! Gruppiere nach VisitID und benutze 'min' und' max'. Brownie weist darauf hin, beide Antworten auf eine möglicherweise mehrdeutige Frage zu geben – Jeff

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

ein wenig Hack benutzt für jeden Besuch beginnt alles Tage und Ende Tage hinzuzufügen und den Unterschied zu bekommen.

Verwandte Themen