Некоторое время назад я задал вопрос 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()
записи, найденные в группировке, а не самые последние.
Как мне обойти эту проблему? Я понимаю, что у меня есть первое решение, которое возвращает мне правильные данные, но на это уходит слишком много времени.
Спасибо за помощь!