2017-03-06 39 views
2

我有一些组从我的SQL查询返回的记录从哪里获得员工姓名,当月休假的他开始和结束日期雇员的叶子总数。我的问题是我得到了同一员工的两条记录,但是有不同的休假日期。现在,我想让他休假时该员工的所有日期(应结合他的两个假期数据)。如何获得在C#

我的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); 
      } 
} 

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

+0

请分享您的C#代码。 –

+0

按员工姓名对数据集中的记录进行分组 –

+0

您最近在做什么?实体框架还是什么? – Worthy7

回答

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))); 

剩下的只是简单的LINQ为WhereSelectMany是项目,结果压扁成相同的序列

编辑
作为您的意见:如果你有leaveList[index]你的数据,那么你就只需更换“托马斯”与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))); 
要分配离开日期
+0

at ** e.Emp_Name **它给出错误**不能将类型字符串转换为布尔**。 –

+0

错过了seconde'='。现在检查。 –

+0

现在在e上发生错误: 错误\t名为'e'的本地或参数不能在此作用域中声明,因为该名称在封闭局部作用域中用于定义本地或参数 –

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) 
     } 
    } 
+0

这个EmployeeList将是包含我的emp名称,StartDate,EndDate的列表吗? –

+0

什么是** listDateTime **行someList.listDateTime.Add(tempDate); –

+0

@munmunpoddar根据您的修改更新了答案。 –

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