题
我们有一个与他们的游泳者的数据库。 要创建一个排名,我们希望获得每个运动员的最快时间。
var rankings = (
from r in _db.Results
orderby r.swimtime
group r by r.athleteid into rg
select new
{
AthleteId = rg.Key,
FirstName = rg.Min(f2 => f2.Athlete.firstname),
Swimtime = rg.Min(f8 => f8.swimtime),
hours = rg.Min(f9 => f9.swimtime.Hours),
minutes = rg.Min(f10 => ("00" + f10.swimtime.Minutes.ToString()).Substring(("00" + f10.swimtime.Minutes.ToString()).Length - 2)), // to get 2 digits in minutes
seconds = rg.Min(f11 => ("00" + f11.swimtime.Seconds.ToString()).Substring(("00" + f11.swimtime.Seconds.ToString()).Length - 2)), // to get 2 digits in seconds
milliseconds = rg.Min(f12 => (f12.swimtime.Milliseconds.ToString() + "00").Substring(0, 2)), // because miliseconds are not always filled
}
);
.
现在排名是正确创建的,但所示的时间不是。
我知道问题是什么,但不知道如何解决它:
在数据库中我们有一个有2次:00:01:02:10(1min2sec10)和00:00:56:95(56sec95)中的游泳者
结果我们得到的时间是分钟(= 00)的最小值,秒(= 02)的最小值,毫秒(= 10)的最小值 导致时间为00:00:02:10。
我们应该得到的是最快时间的小时,分钟,秒和毫秒(= 00:00:56:95)
任何关于如何解决这个问题的想法?
解决方案
This should do the trick:
from result in db.Results
group result by result.AthleteId into g
let bestResult = (
from athleteResult in g
orderby athleteResult.SwimTime
select athleteResult).First()
orderby bestResult.SwimTime
select new
{
AthleteId = bestResult.Athlete.Id,
FirstName = bestResult.Athlete.FirstName,
BestTime = bestResult.SwimTime,
}
The query fetches the best result from a group (all results from a single athelete), orders by that result, and uses that result to populate the final result.
其他提示
Stay away from calling .First on groups, as that can cause automatic requerying due to the difference between LINQ's group (key and elements) vs SQL's group (key and aggregates).
Instead, get the minSwimTime once and let it be.
var rankings =
from r in _db.Results
group r by r.athleteid into rg
let minSwimTime = rg.Min(x => x.swimtime)
select new
{
AthleteId = rg.Key,
FirstName = rg.Min(f2 => f2.Athlete.firstname),
Swimtime = minSwimTime,
hours = minSwimTime.Hours,
minutes = ("00" + minSwimTime.Minutes.ToString()).Substring(("00" + minSwimTime.Minutes.ToString()).Length - 2), // to get 2 digits in minutes
seconds = ("00" + minSwimTime.Seconds.ToString()).Substring(("00" + minSwimTime.Seconds.ToString()).Length - 2), // to get 2 digits in seconds
milliseconds = minSwimTime.Milliseconds.ToString() + "00").Substring(0, 2), // because miliseconds are not always filled
};
Also - don't do string formatting in the database. Database servers have better things to do than turn datetimes into text.