【问题标题】:How to get total number of leaves of an employee in c#如何在c#中获取员工的总休假数
【发布时间】:2017-03-06 19:22:55
【问题描述】:

我从我的 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

在上面的输出中,Thomas 在本月两次休假。所以我想要托马斯在 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 查询中获得的任何员工。

【问题讨论】:

  • 请也分享您的 C# 代码。
  • 按员工姓名对数据集中的记录进行分组
  • 你是怎么做到的?实体框架什么的?
  • @KobyDouek 我已经编辑了我的问题。

标签: c# asp.net sql-server


【解决方案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 是将结果投影并展平到相同的序列中

编辑
作为您的 cmets:如果您的数据在 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)));

【讨论】:

  • e.Emp_Name 它给出了错误 Cannot convert type string to bool.
  • 错过了第二次=。立即检查。
  • 现在在 e 上出现错误:错误不能在此范围内声明名为“e”的本地或参数,因为该名称在封闭的本地范围中用于定义本地或参数
  • 显然,您当前的作用域中有另一个名为 e 的变量。我已经改成 emp...随意改成你想要的任何东西
  • 我已经根据我的更改了你的代码:IEnumerable leaveDates = leaveList.Where(item2 => item2.Emp_Name == leaveList[index].Emp_Name).SelectMany(item2 => Enumerable. Range(0, item2.leaveList[index].end_date.Subtract(item2.leaveList[index].start_date).Days + 1).Select(d => tem2.leaveList[index].start_date.AddDays(d))) ;但这也给出了错误:CS1061“LeaveData”不包含“leaveList”的定义,并且找不到接受“LeaveData”类型的第一个参数的扩展方法“leaveList”(您是否缺少 using 指令或程序集引用? )
【解决方案2】:

具有以下属性的类

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

【讨论】:

  • 这个 EmployeeList 将是包含我的员工姓名 StartDate,EndDate 的列表?
  • 还有 someList.listDateTime.Add(tempDate); 行中的 listDateTime 是什么
  • 但在这里我希望列表仅针对 leaveList[index] 指向的那个员工进行迭代
  • 例如这里的 leaveList[index] 指向 Thomas,所以它应该只迭代 Thomas 的叶子,即从 6-10 到 21-29。
  • 查看答案,它会返回您期望的相同结果,但无论如何 sn-p 将绑定所有员工的所有休假日期.. 进一步您可以过滤任何特定员工按你的需要
【解决方案3】:

看到你想为“现任员工”分配休假日期的要求对我来说似乎很容易,并且可以在 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

【讨论】:

    猜你喜欢
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 2018-11-11
    • 2014-01-07
    相关资源
    最近更新 更多