如何在c#中获取员工的总叶数

时间:2017-03-06 08:16:20

标签: c# asp.net sql-server

我正在从我的SQL查询返回一些记录集,其中我获得了员工姓名以及当月休假的开始和结束日期。我的问题是我得到了两个同一员工的记录但是有不同的休假日期。现在,我希望他休假时该雇员的所有日期(应该将他的假期数据合并)。

我的SQL查询是:

SELECT distinct emp.emp_name, 
       NULL as start_date,
       NULL as end_date 
FROM employee_details emp 
WHERE emp.group_name = 'A' and 
      Emp_Id not in (SELECT distinct emp.Emp_Id 
                     FROM employee_details emp, offshore_leave_calendar olc 
                     WHERE emp.emp_id = olc.emp_id AND 
                           emp.group_name = 'A' and 
                           datepart(mm,olc.start_date) = datepart(mm, getdate()))
union 

SELECT distinct emp.emp_name,
       olc.Start_Date,
       olc.End_Date 
FROM employee_details emp, offshore_leave_calendar olc     
WHERE emp.emp_id = olc.emp_id AND 
      emp.group_name = 'A' and 
      datepart(mm, olc.start_date) = datepart(mm,getdate())

上述查询的输出是:

Emp_Name            start_date               end_date
John         
Sophia       
Olivia
Davis          3/20/2017 12:00:00 AM    3/24/2017 12:00:00 AM
Clark          3/21/2017 12:00:00 AM    3/24/2017 12:00:00 AM
Paul         
Thomas         3/21/2016 12:00:00 AM    3/29/2016 12:00:00 AM
Thomas         3/6/2017 12:00:00 AM     3/10/2017 12:00:00 AM

在上面的输出中托马斯在本月休假两次。因此,我想要托马斯在C#列表中休假时的所有日期。输出日期应为:

3/06/2016
3/07/2016
3/08/2016
3/09/2016
3/10/2016
3/21/2016
3/22/2016
3/23/2016
3/24/2016
3/25/2016
3/26/2016
3/27/2016
3/28/2016
3/29/2016

有人可以帮我吗?

我有一个列表:

 List<LeaveData> leaveList = new List<LeaveData>();

其中LeaveData类有以下三个定义:

public string Emp_Name { get; set; }
public DateTime? start_date { get; set; }
public DateTime? end_date { get; set; }

对于每月的每个日期,我想分配一名员工,不应该分配休假的员工。因此,我循环了当月的所有日期,并编写了此代码,以查找员工休假的日期:

for (int i = 0; i < dates.Length; i++)
{
    for (DateTime? date = leaveList[index].start_date; date <= leaveList[index].end_date; date = date.Value.AddDays(1))
            {
                allDates.Add(date);
            }
}

其中index是从0到7的计数(在这种情况下)。索引将指向我从SQL查询中获得的任何员工。

3 个答案:

答案 0 :(得分:1)

假设您有一份C#

的员工名单
List<Employee> employees = ... 

IEnumerable<DateTime> leaveDates = 
    employees.Where(emp=>emp.Emp_Name == "Thomas")
             .SelectMany(emp =>
                Enumerable.Range(0, emp.EndDate.Subtract(emp.StartDate).Days + 1)
                          .Select(d => e.StartDate.AddDays(d)));

解释

这将获得两个日期之间的日期范围:

Enumerable.Range(0, e.EndDate.Subtract(e.StartDate).Days + 1)
                          .Select(d => e.StartDate.AddDays(d)));

其余的只是Where的简单linq而SelectMany是将结果投影并展平为相同的序列

修改
作为您的评论:如果您的数据位于leaveList[index],那么您只需将“Thomas”替换为leaveList[index].Emp_Name即可。而且我还添加了空日期检查:

IEnumerable<DateTime> leaveDates = 
        employees.Where(emp=>emp.Emp_Name == leaveList[index].Emp_Name && 
                             emp.StartDate.HasValue && emp.EndDate.HasValue)
                 .SelectMany(emp =>
                     Enumerable.Range(0,
                                emp.EndDate.Value.Subtract(emp.StartDate.Value).Days + 1)
                              .Select(d => e.StartDate.Value.AddDays(d)));

答案 1 :(得分:0)

具有以下属性的类

public class EmployeeLeave
{
   public string empName {get; set;}
   public List<DateTime> LeavesDate {get;set;}
}

迭代所有员工

var allEmployeeLeaveList = new List<EmployeeLeave>();

  foreach(var employee in LeaveData)
  {
    var tempDate = employee.StartDate.valueOrDefault();
    while((employee.EndDate.valueOrDefault() - tempDate).TotalDays > 0)
        {
         if( allEmployeeLeaveList .Any(x=>x.empName == employee.Emp_Name ))
           {
              allEmployeeLeaveList .Where(x=>x.empName == employee.Emp_Name    ).LeavesDate .Add(tempDate);
           }
       else
           {
        allEmployeeLeaveList.Add(new EmployeeLeave
                                     {
                                      empName  = employee.Emp_Name ,
                                      LeavesDate = new List<DateTime>  
                                                     {tempDate}         
                                      });
           }

        tempDate.AddDays(1)
        }
  }

答案 2 :(得分:0)

看到要求将“离开日期”分配给“现在的员工”的要求对我来说似乎很容易,并且可以在sql本身中完成,只要我们首先获得完整的信息。

分配员工的标准是什么? 假设它是另一个CTE,我已经研究了你的输出。

declare @t table(Emp_Name varchar(50),start_date datetime,end_date datetime)
insert into @t VALUES
('John',null,null)
,('Sophia',null,null)
,('Olivia',null,null)
,('Davis','3/20/2017 12:00:00 AM ',   '3/24/2017 12:00:00 AM')
,('Clark','3/21/2017 12:00:00 AM','3/24/2017 12:00:00 AM')
,('Paul',null,null)
,('Thomas','3/21/2016 12:00:00 AM',    '3/29/2016 12:00:00 AM')
,('Thomas','3/6/2017 12:00:00 AM',     '3/10/2017 12:00:00 AM')
;With CTE as
(
select  *,ROW_NUMBER()over(partition by Emp_Name order by start_date)RN 
,DATEDIFF(day,start_date,end_date) rn1
from @t
where start_date is not null

)
,CTE1 AS(

select Emp_Name,start_date , end_date,rn,rn1 from cte

UNION ALL
SELECT c.Emp_Name,DATEADD(day,1,c1.start_date), c.end_date,c1.rn
,c1.rn1
FROM cte c
inner join cte1 c1 on c.Emp_Name=c1.Emp_Name
where c.rn=c1.rn
and  C1.start_date<c.end_date
)

SELECT Emp_Name
,start_date leavedates 
FROM CTE1
order by Emp_Name