我有一个表格,可以将卡车分配给用户,使用他们的身份将每个分配链接到各自的实体。只能选择卡车/用户的最后一次分配。我使用以下LINQ来获取我需要的值
var query = (from ta in TruckAllocations
where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
group ta by ta.UserId into grp
let MaxDate = grp.Max(g => g.CreatedOn)
from g in grp
where g.CreatedOn == MaxDate
select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });
我遇到的问题是分配给同一辆卡车的两个用户是查询结果,我只想要分配最后一个。结果示例
47 26 224 2014-03-28 10:47 AM 48 3 149 2014-03-31 10:25 AM 1048 2 575 2014-04-04 1:14 PM 1049 23 575 2014-04-09 9:15 AM 1050 56 322 2014-04-09 2:27 PM
如您所见,用户[2和23]被分配了相同的卡车[575]
我想要的结果是:
47 26 224 2014-03-28 10:47 AM 48 3 149 2014-03-31 10:25 AM 1049 23 575 2014-04-09 9:15 AM 1050 56 322 2014-04-09 2:27 PM
记录1048,因为他不是分配给卡车的最后一个用户而未显示。
有没有办法在对中获得区别,其中对中的每个值必须是唯一的
更新
我也试过
var query = (from ta in TruckAllocations
where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
group ta by ta.TruckId into grp
let MaxDate = grp.Max(g => g.CreatedOn)
from g in grp
where g.CreatedOn == MaxDate
select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });
结果是:
6 54 3 2014-03-04 7:03 PM 8 63 4 2014-03-13 12:36 PM 10 626 4 2014-03-13 2:10 PM 13 12 4 2014-03-20 4:18 PM 21 8 3 2014-03-20 6:21 PM 42 10 3 2014-03-21 1:09 PM 43 3 26 2014-03-26 5:35 PM 44 32 1 2014-03-27 8:53 AM 47 224 26 2014-03-28 10:47 AM 48 149 3 2014-03-31 10:25 AM 1049 575 23 2014-04-09 9:15 AM 1050 322 56 2014-04-09 2:27 PM
它确实只为卡车提供了一个卡车/用户,因为记录[1048]未被退回,但现在我已经使用4,3,26分配给多辆卡车,当他们只能分配一个
使用TruckId和UserId进行分组会将分配给两个用户的卡车添加到由TruckId分组的卡车中。
var query = (from ta in TruckAllocations
where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
group ta by new {ta.TruckId, ta.UserId} into grp
let MaxDate = grp.Max(g => g.CreatedOn)
from g in grp
where g.CreatedOn == MaxDate
select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });
** UPDATE2 **
得到我想要的解决方案是查询按UserId分组的表(有问题的第一个查询),然后查询由TruckId(有问题的第二个查询)分组的表。然后查询两个结果以获得卡车和用户的匹配,如下所示:
var assigned = (from t1 in query1
from t2 in query2
where t1.Truck == t2.Truck && t1.User == t2.User
select new {t1.Key, t1.Truck, t1.User, t1.Date}).ToList();
想知道是否有更好的方法来做到这一点。
答案 0 :(得分:2)
您可以执行类似的操作(组,按需要的元素降序排序)。
更习惯于流利的语法,所以......
var result = TruckAllocations
.Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
.GroupBy(ta => ta.UserId)
//take the first element of each group, which will be the one with the max CreatedOn date
.Select(g=> g.OrderByDescending(m => m.CreatedOn).First())
.Select(m => new {
Key = m.TruckAllocationId,
Truck = m.TruckId,
User = m.UserId,
Date = m.CreatedOn
});
修改强>
您可以通过一步或两步完成此操作。
注意:如果给定用户使用的所有卡车后来被另一个用户使用=>此用户不会出现在列表中。
2步版
var lastDateByTruck = TruckAllocations
.Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
.GroupBy(m => m.TruckId)
.Select(m => new
{
TruckId = m.Key,
CreatedOn = m.Max(x => x.CreatedOn)
});
var result = from allocation in TruckAllocations
join lastUsage in lastDateByTruck on new
{
allocation.TruckId,
allocation.CreatedOn
} equals new
{
lastUsage.TruckId,
lastUsage.CreatedOn
}
group allocation by allocation.UserId
into g
select new
{
UserId = g.Key,
TruckId = g.First().TruckId,
CreatedOn = g.First().CreatedOn
};
一体化语法流利:
var lastDateByTruck = TruckAllocations
.Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
.GroupBy(m => m.TruckId)
.Select(m => new
{
TruckId = m.Key,
CreatedOn = m.Max(x => x.CreatedOn)
})
.Join(TruckAllocations, x => new{x.TruckId, x.CreatedOn}, y => new{y.TruckId, y.CreatedOn}, (x, y) => y)
.GroupBy(m => m.UserId)
.Select(g => new
{
UserId = g.Key,
TruckId = g.First().TruckId,
CreatedOn = g.First().CreatedOn
});