2016-04-28 60 views
2

我正在爲以下問題尋找SQL解決方案。 我想要一連串超過14天病假的員工名單。一段時間SQL獲取狀態

我有一個SQL表如下:

First_name, Last_Name, INDIRECT_ID, SHIFT_DATE 
John, Doe, Sick, 2016-01-01 
John, Doe, Sick, 2016-01-02 
John, Doe, working, 2016-01-03 
John, Doe, Sick, 2016-01-04 
John, Doe, Sick, 2016-01-05 
etc. 

我想通過看這樣做,如果他們生病的10倍(2×5個工作日),在兩個星期。但也許有一個更簡單的解決方案。但現在我也得到重複的答案。

select FIRST_NAME, LAST_NAME 
from (select t.* 
      ,(select count(*) 
       from LABOR_TICKET t2 
       where t2.EMPLOYEE_ID = t.EMPLOYEE_ID and 
        t2.INDIRECT_ID = t.INDIRECT_ID and 
        t2.SHIFT_DATE >= t.SHIFT_DATE and 
        t2.SHIFT_DATE < DATEADD(day, 14, t.SHIFT_DATE)) NumWithin14Days 
     from LABOR_TICKET t 
     where SHIFT_DATE between '2016-01-01' and '2016-04-01' 
    ) LABOR_TICKET 
    INNER JOIN 
         EMPLOYEE ON LABOR_TICKET.EMPLOYEE_ID = EMPLOYEE.ID 

where NumWithin14Days >= 10 AND INDIRECT_ID = 'SICK' 

回答

0

試試這個, 首先在From Date和To Date之間創建所有14天的間隔。 然後檢查每個員工在每個時間間隔內「病態」的計數是14。

DECLARE @ST_DATE DATE='2016-01-01' 
     ,@ED_DATE DATE='2016-04-01' 
;WITH CTE_DATE AS (

    SELECT @ST_DATE AS ST_DATE,DATEADD(DAY,13,@ST_DATE) AS ED_DATE 
    UNION ALL 
    SELECT DATEADD(DAY,1,ED_DATE),DATEADD(DAY,14,ED_DATE) 
    FROM CTE_DATE 
    WHERE DATEADD(DAY,14,ED_DATE) <= @ED_DATE 
) 
SELECT FIRST_NAME, LAST_NAME 
FROM CTE_DATE 
    INNER JOIN LABOR_TICKET ON SHIFT_DATE BETWEEN ST_DATE AND ED_DATE 
WHERE INDIRECT_ID = 'Sick' 
GROUP BY FIRST_NAME, LAST_NAME 
HAVING COUNT(*) >= 14 
+0

謝謝!它在SQL Management Studio中可以正常工作,但是如何將此代碼實現到Microsoft SQL Server Report Builder中,以便用戶可以選擇其開始日期和結束日期。我有這樣的錯誤:「遞歸」CTE_DATE「的列」St_DATE「中的錨點和遞歸部分之間的類型不匹配 – Scaver

+1

找到解決方案。 – Scaver

0

僞代碼給大家的想法爲所有員工

,如果你有一個像下面

create table dates 
(
datetime date 
) 

insert into dates 
select '2016-01-01' 
union all 
select '2016-01-02' 

現在,您可以留下您的主表加入這個像

select 
mt.firstname,dt.date,count(indirect_id) 
from 
datestable dt 
left join 
maintable mt 
on mt.date=dt.date 
and mt.indirect_id='sick' 
group by mt.firstname,dt.date 
having count(indirect_id)>=14 
order by dt.date 
日曆表
0

你應該拋出更多的樣本數據。

試試這個,(我確定它可以和其他樣本數據一起工作),只有很少的東西可以用來過濾數據。

declare @t table(First_name varchar(50), Last_Name varchar(50), INDIRECT_ID varchar(50), SHIFT_DATE date) 
insert into @t values 
('John', 'Doe', 'Sick', '2016-01-01') 
,('John', 'Doe', 'Sick', '2016-01-02') 
,('John','Doe','working','2016-01-03') 
,('John', 'Doe', 'Sick', '2016-01-04') 
,('John', 'Doe', 'Sick', '2016-01-05') 

declare @name varchar(50)='John' 
declare @month int=1 
;With CTE as 
(
    select top 1 First_name,Last_Name,SHIFT_DATE,1 rn from @T where [email protected] 
    and INDIRECT_ID='Sick' order by SHIFT_DATE 
    union all 
    select t.First_name,t.Last_Name,t.SHIFT_DATE, rn+1 from @T t 
    inner join cte c on t.First_name=c.First_name 
where INDIRECT_ID='Sick' 
    and t.SHIFT_DATE=DATEADD(day,1,c.SHIFT_DATE) 
    and t.SHIFT_DATE<='2016-01-31' 
) 

select * from CTE where rn>=14 
0
declare @t table(First_name varchar(50), Last_Name varchar(50), INDIRECT_ID varchar(50), SHIFT_DATE date) 
insert into @t values 
('John', 'Doe', 'Sick', '2016-01-01') 
,('John', 'Doe', 'Sick', '2016-01-02') 
,('John','Doe','working','2016-01-03') 
,('John', 'Doe', 'Sick', '2016-04-04') 
,('John', 'Doe', 'Sick', '2016-05-05') 

select s.* 
     ,u.* 
     ,Sickdays = 
     case 
     when s.indirect_id = 'Sick' and u.indirect_id = 'Sick' then datediff(dd,u.shift_date,s.shift_date) 
     else 0 
     end 
from 
(
select t.*, 
     row_number() over(partition by last_name,first_name order by shift_date desc) rn 
from @t t 
) s 
join  
(select t.*, 
     row_number() over(partition by last_name,first_name order by shift_date desc) rn 
from @t t 
) u on s.last_name = u.last_name and s.first_name = u.first_name and s.rn = u.rn - 1 
where 
     case 
     when s.indirect_id = 'Sick' and u.indirect_id = 'Sick' then datediff(dd,u.shift_date,s.shift_date) 
     else 0 
     end > 13 
+0

請注意日期已本地化爲英國,即yyyymmdd在我的測試數據中。毋庸置疑,如果你有一個員工ID加入,在現實世界中,你可能需要在工作日報告疾病,這並不容易。 –