简体   繁体   中英

LINQ join: selecting the last records in a one-to-many relationship

Let's suppose I have two tables:

  • Employees table : contains fields such as EmployeeId, DepartmentId...
  • Signings/Attendance table : contains fields such as SigningId, Time, EmployeeId, SignType (in or out)...

I am trying to select the last signing from every employee who belongs to a certain department in a certain DateTime (usually DateTime.Now) because I am developing an attendance-based application for my company.

So far I have the following query, which returns EmployeeId and SignType for all employees who meet the previous conditions (department and time). I know this query is supposed to have an extra join (left join to be exact probably thanks to this post I found yesterday) but do not really know how to proceed since it is my first time doing such complex linq queries.

Thanks a lot in advance.

from e in AppDbContext.Employees
join s in AppDbContext.Signings
on e.EmployeeId equals s.EmployeeId
where e.DepartmentId == DepartmentId
&& s.Time.Date == DateTime.Now.Date
select new Aux2()
{
   Id = e.EmployeeId,
   Type = s.SignType,
};

EDIT: subquery attempt

AppDbContext.Employees
.Where(e => e.DepartmentId == DepartmentId )
.Select(e => new Aux2(){
                        Id = e.EmployeeId,
                        Type = AppDbContext.Signings
                                      .Where(s => s.EmployeeId== e.EmployeeId && s.Time.Date==Date)
                                      .OrderByDescending(s => s.Time)
                                      .Take(1)
                                      .Select(s => s.SigType)
                                      .FirstOrDefault()
                    })

You can do in this way:

var maxDateSignsByEmployee = from sign in AppDbContext.Signings.Where(s => s.Time.Date == DateTime.Now.Date)
                             group sign by sign.EmployeeId into res
                             select new{
                                 EmpId = res.Key,
                                 MaxDate = resg.Max(x => x.Time)
                             };

var list = from e in AppDbContext.Employees
          join s in AppDbContext.Signings.Where(s => maxDateSignsByEmployee.Where(m => m.EmpId == s.EmployeeId && m.MaxDate == s.Time).Count() > 0)
          on e.WorkerId equals s.EmployeeId
          where e.DepartmentId == DepartmentId
          select new Aux2()
           {
              Id = e.EmployeeId,
              Type = s.SignType,
           };

It should be what you need. It's a basic response, you can optimize it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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