我正在从我的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查询中获得的任何员工。
答案 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