如何在LINQ中为每个键获取一行

时间:2018-07-30 12:26:29

标签: c# linq entity-framework-6 max

我列出了:

EMP_ID | UPDATED_DATE | MARK
------ | ------------ | ----
111    | 01/01/2015   | 99  
111    | 01/01/2013   | 85  
111    | 01/01/2017   | 80  
222    | 01/01/2011   | 70  
222    | 01/01/2015   | 55  
222    | 01/01/2002   | 60  

我必须为每个ID选择一行,并使用最新的UPDATED_DATE, 在我们的等等中:

EMP_ID | UPDATED_DATE | MARK
------ | ------------ | ----
111    | 01/01/2017   | 80  
222    | 01/01/2015   | 55  

这是订购代码:

empMarksList.OrderBy(x=>x.EMP_ID).ThenBy(y=>y.UPDATED_DATE)

4 个答案:

答案 0 :(得分:11)

使用GroupBy

var items = empMarksList
                   .GroupBy(e => e.EMP_ID)
                   .Select(grp => grp.OrderByDescending(v => v.UPDATED_DATE).First());

或者如果您想要字典:

var dict = empMarksList
              .GroupBy(e => e.EMP_ID)
              .ToDictionary(grp => grp.Key,
                            grp => grp.OrderByDescending(v => v.UPDATED_DATE).First());

答案 1 :(得分:3)

我更喜欢这种变体,但这和Amir的回答是一样的

var query =
    empMarksList
        .GroupBy(x => x.EMP_ID)
        .SelectMany(x => x.OrderByDescending(y => y.UPDATED_DATE).Take(1));

答案 2 :(得分:3)

另一个选择是:

var items = context.EmpMarks
    .GroupBy(e => e.EMP_ID, (k, g) => g
        .FirstOrDefault(e => g.Max(v => v.UPDATED_DATE) == e.UPDATED_DATE));

实际上应该在SQL中生成GROUP BY

答案 3 :(得分:1)

您可以使用以下内容:

var result = empMarksList.GroupBy(x => x.Id)
    .Select(g => 
        g.Aggregate((a, x) => a == null || a.UPDATRED_DATE < x.UPDATRED_DATE ? x : a));

这比使用OrderBy更为麻烦,但是这样您就不会订购所有子集合,这在这里有点过头了,而且会占用更多资源。

编辑: @arekzyla回答后,我意识到我的选择也可以这样写:

var items = empMarksList.GroupBy(
   x => x.Id,
   (k, g) => g.Aggregate((a, x) => a == null || a.UPDATRED_DATE < x.UPDATRED_DATE ? x : a));

可读性较差,但在子集合上只有一个集合演练,而不是两个,这在大多数情况下可以忽略不计。

我不确定在哪种情况下生成的SQL会更理想,因此可能值得检查。