简体   繁体   English

LINQ/C#:加入、分组并选择每个组中的最后一个?

[英]LINQ/C#: Join, Group and Select Last in each group?

Using C# and LINQ, I have a table of employees, only some of whom are active and a table of events.使用 C# 和 LINQ,我有一个员工表,其中只有一些是活跃的,还有一个事件表。 I need to join the table of events to the employees on ID, group the events by employee and select the newest event.我需要将事件表加入 ID 上的员工,按员工对事件进行分组并选择最新的事件。 I've tried things along the line of this but getting crosseyed and nowhere.我已经尝试过类似的方法,但是却眼花缭乱,无处可去。

 var emp = (from em in dc.Employees
                   where (em.Active == true)
                   join ev in dc.Events on em.ID equals ev.Employee orderby ev.Time

OK, by cannibalizing some older code from another project, I got this:好的,通过从另一个项目中提取一些旧代码,我得到了这个:

 var attends = dc.Events               
 .GroupBy(c => c.Employee)
 .Select(x => x.OrderByDescending(y => y.Time).FirstOrDefault())
 .Join(dc.Employees,u => u.Employee,o => o.ID,
        (u, o) => new { o.Name,u.Time,u.EventType}).ToList();

Which seems to work, but now I need to filter for Employees where active is true... where would I do that?这似乎有效,但现在我需要过滤那些 active 为 true 的员工......我会在哪里做?

OK... I think (knock on wood) I got it, in the event it helps someone else, this seems to do it:好的......我想(敲木头)我明白了,如果它帮助别人,这似乎可以做到:

var attends = dc.Events                
 .GroupBy(c => c.Employee)
 .Select(x => x.OrderByDescending(y => y.Time).FirstOrDefault())
 .Join(dc.Employees.Where (z=>z.Active), u => u.Employee,o => o.ID, 
        (u, o) => new { o.Name,u.Time,u.EventType}).ToList();


    }

If not, I'll be back crying...如果没有,我会哭着回来的......

Something like this (it maynot compile):像这样的东西(它可能无法编译):

var emp = (from ii in
        (from em in dc.Employees
               where (em.Active == true)
               join ev in dc.Events on em.ID equals ev.Employee 
        select new { Employee = ev.Employee, Event = ev.Eventid, EventTime = ev.Time})
        group ii by new {ii.EventId} into g
        select new 
        {
           Event = g.Key
        }).ToList();

Seems like this works... kind of sad that I got a down vote because apparently someone felt I hadn't done adequate homework.似乎这行得通......我得到了反对票有点难过,因为显然有人觉得我没有做足够的功课。 Hopefully this will help someone else:希望这会帮助别人:

    var attends = dc.Events                
 .GroupBy(c => c.Employee)
 .Select(x => x.OrderByDescending(y => y.Time).FirstOrDefault())
 .Join(dc.Employees.Where (z=>z.Active), u => u.Employee,o => o.ID, 
        (u, o) => new { o.Name,u.Time,u.EventType}).ToList();

I need to join the table of events to the employees on ID, group the events by employee and select the newest event.我需要将事件表加入 ID 上的员工,按员工对事件进行分组并选择最新的事件。

It seems to me that you want a sequence of Employees, each Employee with his newest event.在我看来,您需要一系列员工,每个员工都有他的最新事件。

Usually if you do a Join followed by a GroupBy, you could also use a GroupJoin:通常,如果你先加入一个 GroupBy,你也可以使用一个 GroupJoin:

var employeesWithNewestEvents = employees.GroupJoin(events,
    employee => employee.Id,        // from each Employee take the primary key
    event => event.EmployeeId,      // from each event take the foreign key to Employee

    // ResultSelector: from each Employee with his zero or more Events, make a new
    (employee, eventsOfThisEmployee) => new
    {
         // select only the Employee properties you plan to use
        Id = employee.Id,
        Name = employee.Name,
        ...

        NewestEvent = eventsOfThisEmployee
            .OrderByDescending(event => event.Time)
            .Select(event => new
            {
                 // Select only the Event Properties you plan to use
                 Id = event.Id,
                 Description = event.Description,
                 ...

                 // not needed, you know the value: EmployeeId = event.EmployeeId
            })
            .FirstOrDefault(),
    })

Note that Employees without events will also be in the selected data.请注意,没有事件的员工也将在所选数据中。 They will have a null value for NewestEvent.它们将具有 NewestEvent 的空值。

If you want to select the complete Employee and its complete latest event you could use the following result selector:如果要选择完整的 Employee 及其完整的最新事件,可以使用以下结果选择器:

(employee, eventsOfThisEmployee) => new
{
     Employee = employee,
     NewestEvent = eventsOfThisEmployee
        .OrderByDescending(event => event.Time)
        .FirstOrDefault(),
});

Be aware that this method will select more properties than you actually need.请注意,此方法将选择比您实际需要的更多的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM