2017-03-06 55 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