在LINQ加入并分组

时间:2017-03-20 09:09:17

标签: entity-framework linq lambda

这是实体和表格结构 -

class Person { int PersonId, string PersonName}
class Report { int ReportId, datetime ReportTime, int PersonId }

Table: Persons
----------------------------
| PersonId  | PersonName   |
----------------------------
|   1       |    Abc       |
---------------------------- 
|   2       |    Xyz       |
---------------------------- 

Table: Reports
----------------------------------------------
| ReportId  |    ReportTime      | PersonId  |
----------------------------------------------
|    10     | 2017-02-27 11:12   |    1      |
---------------------------- -----------------
|    14     | 2017-02-27 15:23   |    1      |
---------------------------- -----------------

我想按如下方式选择数据(Person中的PersonName和报告表中他的Id的最后一条记录) -

-------------------------------------
| PersonName  |      ReportTime     |
-------------------------------------
|   Abc       |    2017-02-27 15:23 |
------------------------------------- 

我如何在Lambda或LINQ中执行此操作?

2 个答案:

答案 0 :(得分:2)

使用Queryable.GroupJoin

from p in db.Persons
join r in db.Reports on p.PersonId equals r.PersonId into g
where g.Any() // if some persons do not have reports
select new {
  p.PersonName,
  ReportTime = g.Max(r => r.ReportTime)
}

Lambda(请注意,对于没有任何报告的人,它将返回Nullable ReportTime,其中包含空值)

db.Persons.GroupJoin(
     db.Reports, 
     p => p.PersonId, 
     r => r.PersonId,
     (p,g) => new { p.PersonName, ReportTime = g.Max(r => (DateTime?)r.ReportTime) })

答案 1 :(得分:0)

试试这个:

        List<Person> people = new List<Person>
        {
            new Person {PersonId = 1, PersonName = "AB" },
            new Person {PersonId = 2, PersonName = "CD" },
            new Person {PersonId = 3, PersonName = "EF" },
        };

        List<Report> reports = new List<Report>()
        {
            new Report {ReportId = 1, ReportTime = DateTime.Now, PersonId = 1 },
            new Report {ReportId = 2, ReportTime = DateTime.Now.AddHours(-1), PersonId = 1 },
            new Report {ReportId = 3, ReportTime = DateTime.Now.AddHours(-2), PersonId = 1 },
            new Report {ReportId = 4, ReportTime = DateTime.Now.AddMinutes(-3), PersonId = 2 },
            new Report {ReportId = 5, ReportTime = DateTime.Now, PersonId = 2 }
        };


        var res = (from rep in reports
                   group rep by rep.PersonId into repGrp
                   join ppl in people on repGrp.FirstOrDefault().PersonId equals ppl.PersonId
                   select new
                   {
                       PersonName = ppl.PersonName,
                       ReportDate = repGrp.Max(r => r.ReportTime),
                   }).ToList();
    }