少し前に、SQL Serverに質問しました:group byで集計関数を使用してデータの整合性を維持するにはどうすればよいですか?私はそこで素晴らしい答えを得ましたが、今度は問題が再び発生しました。今回は、プレーンSQLではなくLinqtoSQLを使用しました。
バックストーリー: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()
これはほとんどのフィールドに影響を与えませんが、緯度と経度は、最新のものではなく、グループ化で見つかったレコードにすぎないため、ほとんどの場合正しくありません。
この問題を回避するにはどうすればよいですか?正しいデータを取得する最初のソリューションがあることはわかっていますが、時間がかかりすぎます。
助けてくれてありがとう!