2012-09-18 85 views
1

完整性前段時間我問的問題SQL Server: How do I maintain data integrity using aggregate functions with group by?我有一個很好的答案,但現在的問題再次出現,與LINQ to SQL的這個時間,而不是普通的SQL。LINQ到SQL數據和分組

背景故事:我有滿滿一桌子的GPS數據,它看起來像這樣:

GPS_id,USER_ID,緯度,經度,server_time,device_time

我用下面的LINQ查詢拔出最新的GPS記錄的一組特定的用戶:

var query = 
    from gps in db.gps_data 
    where (from u in db.users 
     select u.user_id).Contains(gps.user_id) 
    group gps by gps.user_id into groupedGPS 
    select groupedGPS; 

然後,我通過它循環,像這樣,但我不得不爲了在prope第一訂購吧迅速搶奪「最新紀錄」。

foreach (var gpsItem in query) { 
    var ordered = gpsItem.OrderByDescending(g => g.device_time); 
    list.Add(ordered.First()); 
} 

這給了我我需要的東西,但在任何時候我有100多個用戶的所有500個+ GPS記錄(以及所有的人都被訪問如此),所以這段代碼被取10+秒,這我認爲不可接受。

然後我把它改成下面

var query = 
    from gps in db.gps_data 
    where (from u in db.users 
     select u.user_id).Contains(gps.user_id) 
    group gps by gps.user_id into groupedGPS 
    select new 
    { 
     GPS_id = groupedGPS.Max(x => x.GPS_id), 
     user_id = groupedGPS.Max(x => x.user_id), 
     latitude = groupedGPS.Max(x => x.latitude), 
     longitude = groupedGPS.Max(x => x.longitude), 
     server_time = groupedGPS.Max(x => x.server_time), 
     device_time = groupedGPS.Max(x => x.device_time) 
    }; 

該查詢似乎更快,因爲據我的理解去所有的不必要的數據永遠不會實際加載到內存中。但是,正如我在幾個月前的原始問題中那樣,我以這種方式失去了數據完整性。有沒有保證,我看到最近的記錄,只是最大值在分組所有字段。這對大多數字段沒有影響,但緯度和經度幾乎都是不正確的,因爲它們僅僅在該分組,而不是最近的版本中發現的max()記錄。

如何解決這個問題?我意識到我有第一個解決方案檢索我正確的數據,但所花費的時間太長。

感謝您的幫助!

回答

1

據我理解你的問題(每用戶ID最新的記錄),這看起來像它會做你要找的內容;

var q = 
    from gps in db.gps_data 
    where (from gps2 in db.gps_data 
      group gps2 by gps2.user_id 
      into g 
      select new {a = g.Key, b = g.Max(f => f.server_time)}) 
      .Contains(new {a = gps.user_id, b = gps.server_time}) 
    select gps; 

它可能會給你重複,如果有多個讀數,同時爲用戶,我假設他們沒有。

+0

編輯:沒關係 - 看起來像工作正常。讓我玩更多... – Mansfield

+0

它的效果很好 - 平均值爲440ms,而不是10s。萬分感謝! – Mansfield

0

以下應該工作,但將執行多個子選擇,所以你需要檢查你的表現,並確保FirstOrDefault與LINQ提供程序的工作原理直列:

var query = 
    from u in db.users 
    select new 
    { 
     u.user_id, 
     latestGPS = (db.gps_data 
        where g.user_id == u.user_id 
        orderby g.server_time descending 
        select g).FirstOrDefault() 
    };