2014-03-28 77 views
0

如何編寫LINQ查詢來僅提取條件的邊界記錄。例如,考慮其代表跟蹤從車輛接收到的數據下面的數據庫表:LINQ查詢設計

enter image description here

我想只獲取記錄47890和47880.這將給開始時間和結束時間的車輛停止時。

現在,在我的查詢中,我獲取所有記錄,然後取第一個和最後一個。此外,查詢需要是通用的,我可能有多個車輛停靠點。例如:

停止1:11:00 AM至1:00 PM

停止2:下午3:00至3:30 PM

等。

這是迄今爲止我所編寫的代碼:下結果與LinqPad測試

var sData = db.Vehicles 
      .Where(v => v.VehicleId == vehicleId) 
      .SelectMany(v => v.GsmDeviceLogs) 
      .Where(gs => gs.DateTimeOfLog > startDate && gs.DateTimeOfLog < endDate && gs.Speed < zeroSpeed && !gs.IgnitionOn) 
      .Select(v => new 
      { 
       DateTimeOfLog = v.DateTimeOfLog, 
       Location = v.Location 
      }).OrderBy(gs => gs.DateTimeOfLog).ToList(); 
+0

您目前的查詢是否返回錯誤的結果?我會在'!gs.IgnitionOn'(在第二個位置)之後提取開始和日期時間以及零速度的條件 - 這樣您將只有零,並且您始終可以從第一個和最後一個條目結果查詢。正如你所描述的那樣,查詢應該非常簡單,你幾乎就在那裏。 – pasty

+0

但是,第一個也可能是最後一個。如果車輛每天停車兩次,那麼應該有2對First和Last。 –

+0

該查詢起作用。但只會給我1首和最後一雙。如果萬一有兩站。它將把它們合併成一個。我需要兩個首先和最後一對兩站。 –

回答

2

。它可以使用T-SQL進行優化並通過存儲過程使用。

var indexedRowsAsc = arr.OrderBy(r => r.DateTimeOfLog) 
         .Select((r, index) => new { Row = r, Index = index}); 

// find intersection of current row and next row with condition (IgnitionOn) 
// intersection can ignore first and last row 
var foundRows = (from a in indexedRowsAsc 
       from b in indexedRowsAsc 
       where a.Index == (b.Index -1) && 
         a.Row.IgnitionOn != b.Row.IgnitionOn 
       select new {a, b} 
       ).ToArray(); 

var firstRow = arr.OrderBy(r => r.DateTimeOfLog).FirstOrDefault(); 
var lastRow = arr.OrderByDescending(r => r.DateTimeOfLog).FirstOrDefault(); 

// union found rows with first and last row 
var distinctFoundRows = foundRows.Select(fr => fr.a.Row) 
         // comparer can be added for union for proper distinct gathering 
         .Union(foundRows.Select(fr => fr.b.Row)) 
         // add first and last row 
         .Union(new Vehicle[]{firstRow}) 
         .Union(new Vehicle[]{lastRow}) 
         .Where(r => r!= null) 
         .OrderBy(r => r.DateTimeOfLog) 
         .ToArray(); 

// find result by grouping rows where IgnitionOn == 0 
int groupId = 1; 
var result = distinctFoundRows 
      .Select(row => new {Row =row, GroupId = (row.IgnitionOn == 0? groupId: ++groupId)}) 
      .Where(res => res.Row.IgnitionOn == 0) 
      .GroupBy(res => res.GroupId) 
      .Select(gr => new {First = gr.First().Row, Last = gr.Last().Row}) 
      .ToArray(); 

查找列中更改的值的祕訣是self joining

enter image description here