1

前段时间我问了SQL Server 的问题:如何使用带有 group by 的聚合函数来维护数据完整性?我在那里得到了很好的答案,但现在问题又出现了,这次是使用 Linq to SQL 而不是普通的 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;

然后我像这样循环遍历它,但我必须先订购它才能正确获取“最新记录”。

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()在分组中找到的记录,而不是最近的记录。

我该如何解决这个问题?我意识到我有第一个解决方案来检索正确的数据,但是它花费的时间太长了。

谢谢您的帮助!

4

2 回答 2

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;

如果用户同时有多个读数,它可能会给你重复,我假设他们不是。

于 2012-09-18T18:26:57.480 回答
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()
    };
于 2012-09-18T18:56:45.563 回答